c# 泛型之约束
1.1类类型约束
有时候可能要求能将类型实参转换为特定的类类型,这是用类类型约束做到的。
public class TestDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : EntityBase { }
如上述代码,TestDictionary<TKey, TValue> 要求类型参数TValue提供的所有类型参数都必须隐式的转换为EntityBase类。
与接口约束不同,不允许多个类类型约束。c#不允许将类型参数约束为string或者System.Nullable<T>,否则就只有单一类型实参可供选择,类型参数就没必要存在了,直接用这个类型即可
1.2接口约束
IComparable是一个接口,可以排序或排序的类型实现
public class Program { public class Container<T, U> { /// <summary> /// 嵌套类 /// </summary> /// <typeparam name="U"></typeparam> public class Nested<U> { public void Method(T t, U u) { } } } public static void Main(string[] args) {
//这时候会报错 不能将类型“System.Text.StringBuilder”用作泛型类型或方法“ConsoleApplication2.BinaryTree<T>”中的类型形参“T”。没有从“System.Text.StringBuilder”到“System.IComparable<System.Text.StringBuilder>”的隐式引用转换。
BinaryTree<StringBuilder> b = new BinaryTree<StringBuilder>();
//下面的就可以
BinaryTree<int> b = new BinaryTree<int>();
BinaryTree<string> b = new BinaryTree<string>();
} }
//这是为了这个类中的方法实现而加的对参数的约束。
public class BinaryTree<T> where T : IComparable<T> {
}
1.3struct/class约束
IFormattable接口提供了ToString()方法的定义,使用该方法可以将对象的值按照指定的格式转化成字符串的功能
下面代码是示例:
public class Program { static void Main(string[] args) { Person p1 = new Person { FirstName = "XY", LastName = "CN" }; PersonFormatter pf = new PersonFormatter(); string s1 = p1.ToString("CN", pf); Console.WriteLine(s1); string s2 = p1.ToString("EN", pf); Console.WriteLine(s2); string s3 = p1.ToString("EN", null); Console.WriteLine(s3); Console.ReadKey(); } } class PersonFormatter : IFormatProvider,ICustomFormatter { public string Format(string format, object arg, IFormatProvider formatProvider) { Person person = arg as Person; switch(format) { case "CH":return string.Format("{0} {1}",person.LastName,person.FirstName); //$"{person.LastName} {person.FirstName}"; case "EN": return string.Format("{0} {1}", person.FirstName, person.LastName);//$"{person.FirstName} {person.LastName}"; default: return string.Format("{0} {1}", person.LastName, person.FirstName);//$"{person.LastName} {person.FirstName}"; } } public object GetFormat(Type formatType) { if (formatType == typeof(ICustomFormatter)) return this; return null; } } class Person:IFormattable { public string FirstName { set; get; } public string LastName { set; get; } public string ToString(string format, IFormatProvider formatProvider) { ICustomFormatter customFormatter = formatProvider as ICustomFormatter; if (customFormatter == null) return this.ToString(); return customFormatter.Format(format, this, null); } }