源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

c# in depth的泛型实现实例代码

  • 时间:2021-06-29 06:11 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:c# in depth的泛型实现实例代码
[b]1.默认值表达式 [/b]如果已经明确了要处理的类型,也就知道了它的“默认”值。不知道要引用的类型,就不能直接指定默认值。不能使用null,因为它可能不是一个引用类型,不能使用0,因为它可能不是数值类型。虽然很少需要用到默认值,但它偶尔还是有用的。Dictionary<TKey,TValue>就是一个好的例子,它有个TryValue方法,它的作用有点儿像对数值类型进行处理的TryParse方法:他用一个输出参数来接收你打算获取的值,用一个Boolean返回值显示它是否成功。这意味着方法必须用TValue类型的值来填充输出参数。请记住,输出参数必须在方法正常返回之前赋值。 为了满足这方面的要求,c#2提供了默认值表达式。虽然c#语言规范没有说他是一个操作符,但可以把它看做是与typeof相似的操作符,只是返回值不一样罢了。
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 默认值表达式 {     class Program     {         static int CompareToDefault<T>(T value)         where T : IComparable<T>         {             return value.CompareTo(default(T));         }         static void Main(string[] args)         {             Console.WriteLine(CompareToDefault("x"));             Console.WriteLine(CompareToDefault(10));             Console.WriteLine(CompareToDefault(0));             Console.WriteLine(CompareToDefault(-10));             Console.WriteLine(CompareToDefault(DateTime.MinValue));         }     } }
运行结果: [img]http://files.jb51.net/file_images/article/201311/20131120095600.jpg?2013102095940[/img] 在上述代码中,我们为泛型方法使用了3种不同的类型:string,int和DateTime. CompareToDefault方法规定只能使用实现了IComparable<T>接口的类型作为参数,这样才能为传入的值调用ComparTo<T>.传入的值要和类型的默认值进行比较。string是引用类型,默认值是null—根据有关CompareTo的文档,所有引用类型的值都要大于null,所以第一个输出的结果是1,随后三行和int的默认值进行比较,显示int的默认值是0.最后一行输出0,显示了DateTime.MinValue就是DateTime的默认值。 如果传递的参数是null,上述代码会抛出NullReferenceException异常。 [b]2.直接比较 [/b]虽然上述代码演示了如何进行比较,但我们并不是总是愿意限制我们自己的类型来实现IComparable<T>或者它的姊妹接口IEquatable<T>,后者提供了一个强类型的Equals(T)方法,以弥补所有类型都具备的Equals(object)的不足。如果没有接口允许我们访问一些额外的信息,那么我们能做的事情就很少了。只能调用Equals(object)。如果要比较的值时值类型,它会造成装箱。 如果一个类型是未约束的,就可以使用==和!=操作符,但只能将该类型的值与null进行比较。不能直接比较两个T类型的值(会报错,无法通过编译),如果类型实参是一个引用类型,会进行正常的引用比较。如果为T提供的类型实参是一个非可空值类型,与null进行比较总是不相等(这样一来,JIT编译器就可以移除这个比较)。如果类型实参是可空值类型,那么就会自然而然的与类型的空值进行比较。 如果一个类型参数被约束成值类型,就完全不能使用==和!=。如果被约束成引用类型,那么具体执行的比较将完全取决于类型参数被约束成什么类型。如果它只是一个引用类型,那么执行的是简单的引用比较。如果被进一步约束成继承自某个重载了==和!=操作符的特定类型,就会使用重载运算符。但要注意,假如调用者指定的类型实参恰巧也进行了重载,那么这个重载操作符是不会使用的。
[u]复制代码[/u] 代码如下:
using System.Text; using System.Threading.Tasks; namespace 直接比较实现 {     class Program     {         static bool AreReferencesEqual<T>(T first, T second)             where T:class         {             return first == second;         }         static void Main(string[] args)         {             string name = "Joy";             string intro1 = "My name is "+name;             string intro2 = "My name is "+name;             Console.WriteLine(intro1==intro2);             Console.WriteLine(AreReferencesEqual(intro1,intro2));         }     } }
运行结果为: [img]http://files.jb51.net/file_images/article/201311/20131120095658.jpg?201310201000[/img] 虽然string 重载了==,但在执行的比较中是不会用这个重载的。基本上,在说编译AreReferencesEqual<T>时,编译器根本不知道有哪些重载可用,就好比传入的只是object类型的参数。 并非只有操作符才有这个问题,遇到泛型类型时,编译器会在编译未绑定时就解析好所有方法重载,而不是等到执行时,才去为每个可能的方法调用重新考虑是否存在更具体的重载。例如,Console.WriteLine(default(t));这个语句总是被解析成Console.WriteLine(object object),即使为T传递的类型恰好就是string,也不会调用Console.WriteLine(string value),这好比普通方法重载是发生在编译时,而不是执行时。 需要对值进行比较时,有两个相当有用的类,他们是EqualityComparer<T>和Comparer<T>,两者都位于System.Collection.Generic命名空间中。他们分别实现了IEqualityComparer<T>(适合对字典进行比较和哈希处理)和IComparer<T>(适合排序)。这两个类的Default属性能返回一个实现,能为特点的类型采取正确的比较操作。 说明:泛型比较接口  共有四个主要的泛型接口可用于比较。IComparer<T>和IComparable<T>用于排序(判断某个值是小于、等于还是大于另一个值),而IEqualityComparer<T>和IEquatable<T>通过某种标准来比较两个项的相等性,或查找某个项的散列(通过相等性方式匹配) 如果换一种方式来划分这四个接口,IComparer<T>和IEqualiyComparer<T>的实例能比较两个不同的值,而IComparer<T>和IEquatable<T>的实例则可以比较它们本身和其他值。 [b]3.一个完整的比较实例,表示一对值 [/b]这是一个完整的实例,它实现了一个有用的泛型类型,也就是一个Pair<T1,T2>,用于容纳两个值,类似键值对,但这两个值之间没有任何关系。 除了提供属性来访问值本身之外,我们还覆盖了Equals和GetHashCode方法,从而使这个类型的实例能很好的作为字典中的键来使用。  pair<T1,T2>类
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 表示一对值的泛型类 {     public sealed class Pair<T1, T2> : IEquatable<Pair<T1, T2>>     {         private static readonly IEqualityComparer<T1> FirstComparer = EqualityComparer<T1>.Default;         private static readonly IEqualityComparer<T2> SecondComparer = EqualityComparer<T2>.Default;         private readonly T1 first;         private readonly T2 second;         public Pair(T1 first, T2 second)         {             this.first = first;             this.second = second;         }         public T1 First { get { return first; } }         public T2 Second { get { return second; } }         public bool Equals(Pair<T1, T2> other)         {             return other != null && FirstComparer.Equals(this.First, other.First) && SecondComparer.Equals(this.Second, other.Second);         }         public override bool Equals(object obj)         {             return Equals(obj as Pair<T1,T2>);         }         public override int GetHashCode()         {             return FirstComparer.GetHashCode(first) * 37 + SecondComparer.GetHashCode(second);         }     } }
Pair<T1,T2>辅助类
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 表示一对值的泛型类 {     public static class Pair     {         public static Pair<T1, T2> Of<T1, T2>(T1 first, T2 second)         {             return new Pair<T1, T2>(first,second);         }     } }
主体方法
[u]复制代码[/u] 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 表示一对值的泛型类 {     class Program     {         static void Main(string[] args)         {             Pair<string, string> pair1 = new Pair<string, string>("hello","world");             Pair<string, string> pair2 = new Pair<string, string>("hello", "world");             Pair<int, string> pair3 = new Pair<int, string>(1,"hello world");             bool c = pair1.Equals(pair2);             bool d = pair2.Equals(pair3);             System.Console.WriteLine(c);             System.Console.WriteLine(d);             System.Console.WriteLine(pair2.GetHashCode());         }     } }
运行结果 [img]http://files.jb51.net/file_images/article/201311/20131120095751.jpg?2013102010047[/img]
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部