欢迎光临
我们一直在努力

C#2.0 和 .NET Framework

而该要求对于服务组件而言是必需的就像您无法在 COM 或 COM+ 中使用 C++ 模板一样) 您还不能在服务组件上使用一般类型。原因是泛型不能满足 COM 可见性要求。System.A rrai 和泛型例如,System.A rrai 类型通过很多一般静态方法进行了扩展。这些一般静态方法专门用于自动执行和简化处理数组的罕见任务。遍历数组并且对每个元素执行操作、扫描数组,以查找匹配某个条件(谓词)值、对数组进行变换和排序等等。代码块 11 这些静态方法的局部清单。代码块 11. System.A rrai 一般方法public abstract class Array{   //Partial list of the static methods:    public static IList<T> AsReadOnly<T> T[] arrai ;T valu    public static int BinarySearch<T> T[] array.;T value,   public static int BinarySearch<T> T[] array.                                     IComparer<T> compar ;U> T[] array,   public static U[] ConvertA ll<T.U> convert                                 Converter<T.;Predicate<T> match    public static bool Exists<T> T[] array.;Predicate<T> match    public static T Find<T> T[] array.;Predicate<T> match    public static T[] FindA ll<T> T[] array.;Predicate<T> match    public static int FindIndex<T> T[] array.;Action<T> action    public static void ForEach<T> T[] array.;T valu    public static int  IndexOf<T> T[] array.;V> K[] keys,   public static void Sort<K. V[] items,                                IComparer<K> compar ;Comparison<T> comparison    public static void Sort<T> T[] array.}System.A rrai 静态一般方法都使用 System 命名空间中定义的下列四个一般委托:public deleg void Action<T> T t ;T y public deleg int Comparison<T> T x.;U> T from public deleg U Converter<T.;public deleg bool Predicate<T> T t ;代码块 12 演示如何使用这些一般方法和委托。用从 1 20 所有整数初始化一个数组。代码通过一个匿名方法和 Action<T> 委托,然后。使用 Array.ForEach 方法来跟踪这些数字。使用第二个匿名方法和 Predicate<T> 委托,代码通过调用 Array.FindA l 方法(返回另一个相同的一般类型的数组)来查找该数组中的所有质数。最后,使用相同的 Action<T> 委托和匿名方法来跟踪这些质数。请注意代码块 12 中类型参数推理的用法。您在使用静态方法时无须指定类型参数。代码块 12. 使用 System.A rrai 一般方法2,int[] number = {1.3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};A ction<int> trace =  deleg int number                     {                        Trace.WriteLin number ;                     };Predicate<int> isPrim =   deleg int number                           {                              switch number                              {                                case 1:case 2:case 3:case 5:case 7:                                case 11:case 13:case 17:case 19:                                    return true;                                 default:                                    return false;                              }                           };trac A rray.ForEach numbers.;isPrim int[] prime = Array.FindA l numbers.;trac A rray.ForEach primes.;也可以得到类似的一般方法。这些方法使用四个相同的一般委托。实际上, System.Collections.Gener 命名空间中定义的类 List <T> 中。您还可以在您的代码中利用这些委托,如以下部分所示。一般集合即性能较差和缺少类型安全。 .NET 2.0 System.Collections.Gener 命名空间中引入了一组一般集合。例如,有一般的 Stack <T> 类和一般的 Queue 类。 Dictionary<K,System.Collect 中的数据结构全部都是基于 Object 因而继承了本文开头描述的两个问题。T> 数据结构等效于非一般的 HashTabl 并且还有一个有点像 SortedList<K,T> SortedDictionari 类。类 List<T> 类似于非一般的 ArrayList 表 1 将 System.Collections.Gener 主要类型映射到 System.Collect 中的那些主要类型。System.Collections.Gener System.CollectComparer<T> ComparT> HashTabl Dictionary<K.LinkedList<T> -List<T> ArrayListQueue<T> QueueT> SortedList SortedDictionary<K.Stack<T> StackICollection<T> ICollectIComparable<T> System.IComparT> IDictionari IDictionary<K.IEnumerable<T> IEnumerIEnumerator<T> IEnumerIList<T> IList该接口的 System.Collections.Gener 中的所有一般集合还实现了一般的 IEnumer <T> 接口。定义如下所示:public interfac IEnumerable<T>{   IEnumerator<T> GetEnumer ;}public interfac IEnumerator<T> : IDisposable{   T Current{get;}   bool MoveNext ;}IEnumerable<T> 提供了对 IEnumerator<T> 迭代器接口的访问,简单说来。该接口用于对集合进行抽象迭代。所有集合都在嵌套结构上实现了 IEnumerable<T> 其中,一般类型参数 T 集合存储的类型。其定义如下所示: 特别有趣的词典集合定义它迭代器的方式。词典实际上是两个类型(而非一个类型)一般参数(键和值)集合。 System.Collection.Gener 提供了一个名为 KeyValuePair<K,V> 一般结构。V>struct KeyValuePair<K.;{V valu    public KeyValuePair K key.;   public K Kei get;set;   public V Valu get;set;}并且是用于实现它 IEnumer <T> 类型。 Dictionari 类将一般 KeyValuePair<K,KeyValuePair <K,V> 简单地存储一般键和一般值组成的对。该结构就是词典作为集合进行管理的类型。V> 结构指定为 IEnumerable<T> 和 ICollection<T> 项参数:T> : IEnumerable<KeyValuePair<K,public class Dictionary<K.T>>,T>>,                               ICollection<KeyValuePair<K.                               //More interfaces{...}V> 中使用的键和值类型参数当然是词典自己的一般键和值类型参数。您无疑可以在您自己的使用键和值对的一般数据结构中完成同样的工作。例如: KeyValuePair<K.T>:IEnumerable<KeyValuePair<K,public class LinkedList<K.T>> where K:IComparable<K>{...}序列化和泛型.NET 允许您具有可序列化的一般类型:[Serializable]publ class MyClass<T>{...}除了耐久坚持对象成员的状态以外,序列化类型时。 .NET 还耐久坚持有关该对象及其类型的元数据。如果可序列化的类型是一般类型并且它包括绑定类型,则有关该一般类型的元数据还包含有关该绑定类型的类型信息。因此,一般类型的每个带有特定参数类型的变形都被视为唯一的类型。例如,您不能将对象类型 MyClass<int> 序列化(而只能将其反序列化)为 MyClass<string> 类型的对象。序列化一般类型的实例与序列化非一般类型没有什么不同。但是反序列化该类型时,您需要通过匹配的特定类型声明变量,并且在向下强制转换从 Deseri 返回的 Object 时再次指定这些类型。代码块 13 显示了一般类型的序列化和反序列化。代码块 13. 一般类型的客户端序列化[Serializable]publ class MyClass<T>{...}MyClass<int> obj1 = new MyClass<int> ;IFormatt formatt = new BinaryFormatt ;FileMode.Create,Stream stream = new FileStream "obj.bin".FileA ccess.ReadWrit ;use stream{obj1    formatter.Seri stream.;SeekOrigin.Begin    stream.Seek 0.;   MyClass<int> obj2;   obj2 = MyClass<int> formatter.Deseri stream ;}IFormatt 基于对象的您可以通过定义 IFormatt 一般版本进行弥补: 请注意。public interfac IGenericFormatter{   T Deserialize<T> Stream serializationStream ;T graph    void Serialize<T> Stream serializationStream.;}您可以通过包括一个基于对象的格式化程序来实现 IGenericFormattpublic class GenericFormatter<F> : IGenericFormattnew                                    where F : IFormatter.{   IFormatt m_Formatt = new F ;   public T Deserialize<T> Stream serializationStream   {      return T m_Formatter.Deseri serializationStream ;   }T graph    public void Serialize<T> Stream serializationStream.   {graph       m_Formatter.Seri serializationStream.;   }}请注意一般类型参数 F 上的两个约束的用法。尽管可以原样使用 GenericFormatter<F>use GenericBinaryFormatt = GenericFormatter<BinaryFormatter>;us GenericSoapFormatter2 = GenericFormatter<SoapFormatter>;但是您还可以将该格式化程序强类型化以使用:public seal class GenericBinaryFormatt : GenericFormatter<BinaryFormatter>{}publ seal class GenericSoapFormatt : GenericFormatter<SoapFormatter>{}强类型化定义的优点是可以跨文件和程序集共享它这与 us 别名相反。唯一的不同之处在于它使用一般格式化程序: 代码块 14 与代码块 13 相同。代码块 14. 使用 IGenericFormatter[Serializable]publ class MyClass<T>{...}MyClass<int> obj1 = new MyClass<int> ;IGenericFormatt formatt = new GenericBinaryFormatt ;FileMode.Create,Stream stream = new FileStream "obj.bin".FileA ccess.ReadWrit ;use stream{obj1    formatter.Seri stream.;SeekOrigin.Begin    stream.Seek 0.;   MyClass<int> obj2;   obj2 = formatter.Deseri stream ;}泛型和远程处理并且可以使用编程或管理配置。请考虑使用泛型并且派生自 MarshalByRefObject 类 MyServer<T> 可以定义和部署利用泛型的远程类。public class MyServer<T> : MarshalByRefObject{...}您才干通过远程处置访问该类。这意味着 T 可序列化的类型或者派生自 MarshalByRefObject 您可以通过将 T 约束为派生自 MarshalByRefObject 来实施这一要求。 只有当类型参数 T 可封送的对象时。public class MyServer<T> : MarshalByRefObject                           where T : MarshalByRefObject{...}您需要指定要取代一般类型参数而使用的确切类型实参。您必须以与语言无关的方式命名这些类型,使用管理类型注册时。并且提供完全限定命名空间。例如,假设类 MyServer<T> 命名空间 RemoteServ 中的顺序集 ServerA ssembl 中定义,并且您希望在客户端激活模式下将其与整型而不是一般类型参数 T 一起使用。该情况下,配置文件中必需的客户端类型注册条目应该是<client url="...som url goe here...">ServerA ssembly"/>   <activ type="RemoteServer.MyServer[[System.Int32]].;</client>配置文件中的匹配主机端类型注册条目是<service>ServerA ssembly"/>    <activ type="RemoteServer.MyServer[[System.Int32]].</service>双方括号用来指定多个类型。例如:[System.String]LinkedList[[System.Int32].]您可以用类似于 C# 1.1 方式配置激活模式和类型注册,使用编程配置时。不同之处在于,当定义远程对象的类型时,您必须提供类型实参而不是一般类型参数。例如,对于主机端激活模式和类型注册,您可以编写如下代码:Type serverTyp = typeof MyServer<int> ;RemotingConfiguration.RegisterA ctivatedServiceTyp serverTyp ;具有以下代码: 对于客户端类型激活模式和位置注册。Type serverTyp = typeof MyServer<int> ;     string url = ...; //some url initiurl RemotingConfiguration.RegisterWellKnownClientTyp serverType.;只须提供类型参数,当实例化远程服务器时。就好像您在使用外地一般类型一样:MyServer<int> obj;obj = new MyServer<int> ;//Use obj客户端还可以选择使用 Activat 类的方法来连接到远程对象。使用 Activator.GetObject 时,除了使用 new 以外。您需要提供要使用的类型实参,并且在显式强制转换返回的 Object 时提供实参类型:string url = ...; //some url initiType serverTyp = typeof MyServer<int> ;MyServer<int> obj;url obj = MyServer<int> Activator.GetObject serverType.;//Use obj您还可以将 Activator.CreateInst 与一般类型一起使用:Type serverTyp = typeof MyServer<int> ;MyServer<int> obj;obj = MyServer<int> Activator.CreateInst serverTyp ;//Use objActivat 还提供 CreateInst 一般版本,实际上。定义如下:只是添加了类型平安的好处: T CreateInstance<T> ;CreateInstance<T>   使用方式类似于非一般方法。Type serverTyp = typeof MyServer<int> ;MyServer<int> obj;obj = Activator.CreateInst serverTyp ;//Use obj泛型无法完成的工作您不能定义一般 Web 服务, .NET 2.0 下。即使用一般类型参数的 Web 方法。原因是没有哪个 Web 服务规范支持一般服务。

赞(0)
未经允许不得转载:福利吧|福利社|fuliba » C#2.0 和 .NET Framework

相关推荐

  • 暂无文章