C#的泛型的类型参数可以有带参数的c泛型构造函数数的约束方式吗

c#泛型使用详解:泛型特点、泛型继承、泛型接口、泛型委托
泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用&参数化类型&将类型抽象化,从而实现灵活的复用。在 NET类库中处处都可以看到泛型的身影,尤其是数组和集合中,泛型的存在也大大提高了程序员
泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。在.NET类库中处处都可以看到泛型的身影,尤其是数组和集合中,泛型的存在也大大提高了程序员的开发效率。更重要的是,C#的泛型比C++的模板使用更加安全,并且通过避免装箱和拆箱操作来达到性能提升的目的。因此,我们很有必要掌握并善用这个强大的语言特性。
C#泛型特点:
1、如果实例化泛型类型的参数相同,那么JIT编辑器会重复使用该类型,因此C#的动态泛型能力避免了C++静态模板可能导致的代码膨胀的问题。
2、C#泛型类型携带有丰富的元数据,因此C#的泛型类型可以应用于强大的反射技术。
3、C#的泛型采用“基类、接口、构造器,值类型/引用类型”的约束方式来实现对类型参数的“显示约束”,提高了类型安全的同时,也丧失了C++模板基于“签名”的隐式约束所具有的高灵活性
C#泛型继承:
C#除了可以单独声明泛型类型(包括类与结构)外,也可以在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型要么以实例化,要么来源于子类(同样是泛型类型)声明的类型参数,看如下类型
class G:C//非法
E类型为C类型提供了U、V,也就是上面说的来源于子类
F类型继承于C,个人认为可以看成F继承一个非泛型的类
G类型为非法的,因为G类型不是泛型,C是泛型,G无法给C提供泛型的实例化
泛型类型的成员:
泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的公有成员。如下图:
泛型接口:vcD4KPHA+Cre60M2907/atcTA4NDNss7K/dKqw7TS0cq1wP27r6Os0qrDtMC01LTT2sq1z9bA4Mn5w/e1xMDg0M2yzsr9PC9wPgo8cD4Kt7rQzc6vzdCjujwvcD4KPHA+Cre60M3Or83Q1qez1tTazq/N0Le1u9gmIzIwNTQwO7rNss7K/cnP06bTw7LOyv3A4NDNo6zV4tCpss7K/cDg0M3NrNH5v8nS1Li9tPi6z7eotcTUvMr4PC9wPgo8cD4KZGVsZWdhdGUgYm9vbCBNeURlbGVnYXRlPFQ+KFQgdmFsdWUpOzwvcD4KPHA+CmNsYXNzIE15Q2xhc3M8L3A+CjxwPgp7PC9wPgo8cD4Kc3RhdGljIGJvb2wgRihpbnQgaSl7Li4ufTwvcD4KPHA+CnN0YXRpYyBib29sIEcoc3RyaW5nIHMpey4uLn08L3A+CjxwPgpzdGF0aWMgdm9pZE1haW4oKTwvcD4KPHA+Cns8L3A+CjxwPgpNeURlbGVnYXRlPHN0cmluZz4gcDIgPSBHOzwvcD4KPHA+Ck15RGVsZWdhdGU8aW50PiBwMSA9IG5ldyBNeURlbGVnYXRlPGludD4oRik7PC9wPgo8cD4KfTwvcD4KPHA+Cn08L3A+CjxwPgq3utDNt723qKO6PC9wPgo8cD4KMaGiQyO3utDNu/rWxta71qez1qGw1Nq3vbeoyfnD98nPsPy6rMDg0M2yzsr9obGhqqGqvLS3utDNt723qKGjPC9wPgo8cD4KMqGiQyO3utDNu/rWxrK71qez1tTas/23vbeozeK1xMbky/uzydSxo6iw/MCoyvTQ1KGiysK8/qGiy/fS/cb3oaK5udTsxvehos72ubnG96OptcTJ+cP3yc+w/LqswODQzbLOyv2jrLWr1eLQqbPJ1LGxvsntv8nS1LD8uqzU2re60M3A4NDN1tCjrLKiyrnTw7e60M3A4NDNtcTA4NDNss7K/aGjPC9wPgo8cD4KM6Git7rQzbe9t6i8yL/J0tSw/Lqs1Nq3utDNwODQzdbQo6zSsr/J0tSw/Lqs1Nq3x7e60M3A4NDN1tChozwvcD4KPHA+Cre60M23vbeoyfnD96O6yOfPwjwvcD4KPHA+CnB1YmxpYyBzdGF0aWMgaW50IEZ1bmN0aW9uTmFtZTxUPihUIHZhbHVlKXsuLi59PC9wPgo8cD4Kt7rQzbe9t6i1xNbY1NijujwvcD4KPHA+CnB1YmxpYyB2b2lkIEZ1bmN0aW9uMTxUPihUIGEpOzwvcD4KPHA+CnB1YmxpYyB2b2lkIEZ1bmN0aW9uMTxVPihVIGEpOzwvcD4KPHA+CtXi0fnKx7K7xNy5ubPJt7rQzbe9t6i1xNbY1Niho9Lyzqqx4NLrxvfO3reoyLe2qLe60M3A4NDNVLrNVcrHt/Gyu82so6zSsr7Nzt63qMi3tqjV4sG9uPa3vbeoyse38bK7zaw8L3A+CjxwPgpwdWJsaWMgdm9pZCBGdW5jdGlvbjE8VD4oaW50IHgpOzwvcD4KPHA+CnB1YmxpYyB2b2lkIEZ1bmN0aW9uMShpbnQgeCk7PC9wPgo8cD4K1eLR+b/J0tS5ubPJ1tjU2DwvcD4KPHA+CnB1YmxpYyB2b2lkIEZ1bmN0aW9uMTxUPihUIHQpIHdoZXJlIFQ6QTs8L3A+CjxwPgpwdWJsaWMgdm9pZCBGdW5jdGlvbjE8VD4oVCB0KSB3aGVyZSBUOkI7PC9wPgo8cD4K1eLR+bK7xNy5ubPJt7rQzbe9t6i1xNbY1Niho9Lyzqqx4NLrxvfO3reoyLe2qNS8yvjM9bz+1tC1xEG6zULKx7fxsrvNrKOs0rK+zc7et6jIt7ao1eLBvbj2t723qMrHt/Gyu82sPC9wPgo8cD4Kt7rQzbe9t6jW2NC0o7o8L3A+CjxwPgrU2tbY0LS1xLn9s8zW0KOss+nP88Dg1tC1xLPpz/O3vbeotcTUvMr4ysexu8SsyM+8zLPQtcSho8jnz8KjujwvcD4KPHA+CmFic3RyYWN0IGNsYXNzIEJhc2U8L3A+CjxwPgp7PC9wPgo8cD4KcHVibGljIGFic3RyYWN0IFQgRjxULFU+KFQgdCxVIHUpIHdoZXJlIFU6VDs8L3A+CjxwPgpwdWJsaWMgYWJzdHJhY3QgVCBHPFQ+KFQgdCkgd2hlcmUgVDpJQ29tcGFyYWJsZTs8L3A+CjxwPgp9PC9wPgo8cD4KY2xhc3MgTXlDbGFzczpCYXNlPC9wPgo8cD4KezwvcD4KPHA+CnB1YmxpYyBvdmVycmlkZSBYIEY8WCxZPihYIHgsWSB5KXsuLi59PC9wPgo8cD4KcHVibGljIG92ZXJyaWRlIFQgRzxUPihUIHQpIHdoZXJlIFQ6SUNvbXBhcmFibGV7fTwvcD4KPHA+Cn08L3A+CjxwPgq21NPaTXlDbGFzc9bQwb249tbY0LS1xLe9t6jAtMu1PC9wPgo8cD4KRre9t6jKx7rPt6i1xKOs1LzK+LG7xKzIz7zMs9A8L3A+CjxwPgpHt723qMrHt8e3qLXEo6zWuLaoyM66ztS8yvi2vMrHtuDT4LXEPC9wPgo8cD4Kt7rQzdS8yvijujwvcD4KPHA+CjGhokMjt7rQzdKqx/O21KGwy/nT0Le60M3A4NDNu/K3utDNt723qLXEwODQzbLOyv2hsbXEyM66zrzZtqijrLa80qq7+dPaobDP1Mq9tcTUvMr4obGjrNLUzqy7pEMjy/nSqsfztcTA4NDNsLLIq6GjPC9wPgo8cD4KMqGiobDP1Mq91LzK+KGx08l3aGVyZdfTvuSx7bTvo6y/ydLU1ri2qKGwu/nA4NS8yvihsaOsobC907/a1LzK+KGxo6yhsLm51OzG99S8yvihsaOsobAmIzIwNTQwO8Dg0M0v0v3Tw8Dg0M3UvMr4obG5ssvE1tbUvMr4oaM8L3A+CjxwPgozoaKhsM/Uyr3UvMr4obGyorfHsdjQ66OsyOe5+8O709DWuLaoobDP1Mq91LzK+KGxo6y3ttDNwODQzbLOyv29q9a7xNy3w87KU3lzdGVtLk9iamVjdMDg0M3W0LXEuavT0Le9t6iho8D9yOejutTav6rKvLXEwP3X09bQo6y2qNLltcTEx7j2b2Jqs8nUsbHkwb+ho7HIyOfO0sPH1Nq/qsq8tcTEx7j2wP3X09bQvNPI69K7uPZUZXN0McDgo6zU2sv8tbHW0Lao0uXBvbj2uau5sre9t6hGdW5jMaGiRnVuYzKjrMjnz8LNvKO6PC9wPgo8cCBhbGlnbj0="center">
我们今天来讨论下泛型的用法。首先说下泛型的概念,用通俗的语言来讲,泛型其实就是类的一个参数,但是要求参数必须是一个类,而不能是一个对象。很多人可能对泛型中T的作用不太理解,其中T在泛型中扮演的角色就相当于一个占位符,确切的说,是类型占位符。凡是出现T的地方都会替换成你所传递的类型。
那么下面我们就来写一个泛型的例子,让大家体验一下泛型的威力。
首先咱们来看常用的List泛型集合
01,List集合,其中T可以是任何类型(int,string,数组类型,甚至是用户自定义的类类型)
List intList = new List();
intList.Add("李晓玲");
intList.Add("章子怡");
foreach (string item in intList)
Console.WriteLine(item);
也可以在声明List时使用类似于数组初始化器的集合初始化器。
例如:List nameList=new List(){“Jack”,”Rose”,”Harvard”};
(该特性在.net3.0以及更高版本中使用)
List常用方法:
1. 要向泛型中添加一个元素:使用Add()方法
添加多个元素:使用AddRange()方法
2.在指定位置插入元素使用Insert()方法
3.访问元素可以通过索引,也可以使用foreach循环遍历
4.删除元素可以使用Remove()或者RemovAt()方法,使用Clear()方法可以删除所有元素。
然后来看下键值对泛型集合Dictionary
C#也为HashTable提供了泛型类型,即Dictionary,通常称为”字典”。
Dictionary存储数据的特点:
1, 存储数据的方式和哈希表类似,也是通过key/value保存元素。
2, 键必须是唯一的。不能为null,但是如果值为引用类型,该值可以为空。
主要属性:count:获取包含的键/值对数
Keys:键的集合
//02,Dictionary集合
Dictionary dic = new Dictionary();
dic.Add("01", "李小龙");
dic.Add("02","李连杰");
foreach (string item in dic.Keys)
Console.WriteLine("key"+item+" value"+dic[item]);
//一次性遍历键和值
foreach (KeyValuePair item in dic)
Console.WriteLine("key"+item.Key+" value"+item.Value);
这时候大家可能会有疑问,为什么要用泛型呢?
泛型有三个好处:
1,实现算法的重用。
在泛型出现之前,我们为了保证性能安全而自定义强类型集合时,就需要为每种类型创建几乎相同自定义集合。这样就会重复劳动而且可维护性差。
2,避免拆箱和装箱。
这点大家可以这样理解,使用ArrayList和HashTable存取变量,会带来频繁的装箱(将值类型转换成引用类型)和拆箱(将引用类型转换成值类型)操作,对性能有所影响。
3,类型安全(编译时会自动检测参数类型)
泛型的特点:
泛型将操作的数据类型定义为一个参数,类型参数使得设计如下类和方法成为可能。这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化类或方法的时候。
使用where约束类型参数
可以使用where约束类型参数:
Where T:struct 中T必须在其继承链中有System.ValueType值类型。
Where T:class 中T必须是引用类型
Where T:new()中T必须有一个默认的构造函数。在有多个约束的类型上,此约束必须列在末尾。
Where T:NameOfBaseClass中T必须派生于NameOfBaseClass指定的类。
当然,泛型不仅能用在类上,也可单独用在类的方法中,它可根据方法参数的类型自动适应各种参数,这样的方法就叫做泛型方法。
Public class Stack2
Public void Push(Stack s, params T[] p)
Foreach(T t in p)
s.Push(t);
原来的类Stack一次只能Push一个数据,这个类Stack2扩展了Stack的功能,可以一次把多个数据压入Stack中,其中Push是一个泛型方法。这个方法的调用示例如下:
Stack stack=new Stack(100);
Stack2 mystack2=new Stack2();
mystack2.Push(x,1,2,3);
string str=string.E
for(int i=0;i<3;i&#43;&#43;)
Str&#43;=stack.Pop().ToString();
结果输出str的&#20540;是64321&&2942 阅读
从根本上说泛型实现了类型和方法的&参数化&,类似于在普通方法调用中,使用参数来告诉方法调用者应该使用什么值。同样,泛型类型和方法也可以让参数告诉它的调用者应该使用什么类型。
3.1 为什么需要泛型
使用泛型可以增加代码的重用
更好的编译时检查,减少运行时的检查
更多的在代码中直接表现的信息——可读性
更多的IDE支持
更好的性能——减少装箱和拆箱
3.2 日常使用的简单泛型
3.2.1 泛型类型和泛型参数
泛型的两种形式
泛型类型(包括类、接口、委托、和结构——但不包括枚举)
概念和术语
类型实参(type argument):在List这类型中T只是一个占位符,使用该类型时,需要使用真实类型代替:List&string&,这里的string类型就是类型实参
未绑定泛型类型(unbound generic type):指的是没有为任何类型提供类型实参。例如:
List&T&,未绑定泛型类型是一种额外的抽象层(对于已构造类型来说)
已构造类型(constructed type):一个泛型类型如果指定了类型参数,就成为一个已构造类型。未绑定泛型类型是已构造类型的蓝图,已构造类型又是实际对象的蓝图
开放类型(open type)和封闭类型(closed type):开放类型 包含一个类型参数(例如,作为类型实参之一或者数组元素类),而 封闭类型 则是不开放的,类型的每个部分都是明确的。
3.3 深化与提高
3.3.1 类型约束
通过约束(constraint)来对泛型(包括泛型方法和泛型类)的类型参数进行限制。在C# 2中约束由上下文关键字where给出,且放到泛型方法或泛型类型声明的末尾,如下:
struct RefSample&T& where T : class
引用类型约束
表示成T : class,必须是为类型参数指定的第一个约束,用于确保使用的类型实参是引用类型
值类型约束
表示成T : Struct,确保使用的类型实参是值类型。如果同时存在多个约束:值类型约束必须是第一个指定的
构造函数类型约束
表示成T : new(),必须是所有类型参数的最后一个约束。作用是:核对所用的类型实参是否有一个无参数的构造函数
转换类型约束(最有用)
表示成class Sample&T& where T : className允许指定另一个类型,类型的实参必须可以通过一致性、引用或装箱转换隐式地转换为该类型。这意味着:可以在类型参数的实例上使用指定类型的成员
转换类型约束的限制
密封类(如:string)
System.Object
System.Enum
System.ValueType
System.Delegate
前面的几种约束按照规定的规则组合在一起
3.3.2 泛型方法类型实参的类型推断
类型推断只适用于泛型方法,不适用于非泛型方法
static List&T& MakeList&T&(T first, T second){...}
//一般使用时这样:
List&string& list = MakeList&string&(&Line 1&,&Line2&)
//通过编译器的类型推断可以这样:
List&string& list = MakeList(&Line 1&,&Line2&)
3.3.3 实现泛型
需要注意的地方
默认值表达式
由于泛型中的类型参可能是引用类型,也可能是值类型,可以通过使用C#提供的默认值表达式(default value expression)(通过default运算符来使用)来解决泛型参数类型的不确定性
遇到泛型类型时,编译器会在编译未绑定的泛型类型时就解析好所有方法重载,而不是等到执行时,
才去为每个可能的方法调用重新考虑是否存在更具体的重载。
//string name = &jon&;
//string intro1 = &My Name is & +
//string intro2 = &My Name is & +
//Console.WriteLine(AreReferenceEqual(str1,str2));
//return:False
//我们看到即使比较的是两个内容相同的string时返回的依然是False
//对于编译器来说:Console.WriteLine(default(T))就是Console.WriteLine(object))
static bool AreReferenceEqual&T&(T first,T second)
where T : class
return first ==
常见的用于比较的泛型接口:
IComparaer&T&和IequalityComparer&T&用于那些能够直接比较两个不同值的类型
IComparable&T&和IEquatable&T&用于实现类型实例本身和其他值直接的比较
3.4 高级泛型
3.4.1静态字段和静态构造函数
静态自动从属于声明它们的类型,在泛型类型中每个封闭类型都有它们自己的静态字段,不同封闭类型的静态字段是各自独立的。静态初始化程序(static initialzer)和静态构造函数(static constructor)也适用于这个规则。
class TypeWithField&T&
public static void PrintField()
Console.WriteLine(field + &: & + typeof(T).Name);
TypeWithField&int&.field = &First&;
TypeWithField&string&.field = &Second&;
TypeWithField&DateTime&.field = &Third&;
TypeWithField&int&.PrintField(); //First: Int32
TypeWithField&string&.PrintField(); //Second: String
TypeWithField&DateTime&.PrintField(); //Third: DateTime
3.4.2 JIT 编译器如何处理泛型
JIT 的职责就是将泛型类型的IL转换为本机代码,使其能够真正运行起来
在处理泛型时,JIT 为每个值类型实参(int,long,Guid...)都创建不同的代码;而所有使用一个引用类型作为类型实参(string,Stream,StringBuilder...)的封闭类型都共享相同的本机代码——这是由于所有引用都具有相同的大小(32位CLR是4个字节,64位为8个字节)。
3.4.3 泛型迭代
如果需要为自己的某个类型实现迭代时,我们可以使用这样的解决办法:显式实现接口IEnumerable,隐式实现IEnumerable&T&接口,由于IEnumerable&T&扩展了IEnumerable,所有两个方法(GetEnumerable&T&)都可以使用相同的返回值。
显式实现接口:
实现接口所规定的方法或属性时,附加接口名作为前缀,即称为&显式接口实现&
3.4.4 反射和泛型
为泛型使用typeof
typeof作用于泛型的两种方式:
获取泛型类型定义(未绑定类型定义)——只需提供声明类型的名称,删除所有类型参数,但保留逗号(如果有的话)(typeof(List&&))
获取特定的已经构造类型——和上面的方式一样,只是保留类型实参即可(typeof(List&int&))
System.Type的属性和方法
两个最重要的方法:
1. ——作用于一个已构造的类型,获取它的泛型类型定义
2. ——作用于泛型类型定义,返回一个已构造类型
程序员新手
本书是世界顶级技术专家“十年磨一剑”的经典之作,在C#和.NET领域享有盛誉。与其他泛泛介绍C#的书籍不同,本...泛型类型不能用以类的构造函数里吗?为什么 - C#当前位置:& &&&泛型类型不能用以类的构造函数里吗?为什么泛型类型不能用以类的构造函数里吗?为什么&&网友分享于:&&浏览:107次泛型类型不能用于类的构造函数里吗?为什么?比如这样
class&Constructor
&&&&public&Constructor&T&(T&temp)
visual&studio提示有错
可我在查看有关泛型的知识的时候,没看到说不能这么用啊,难道我看漏了?
------解决方案--------------------Constructor&T&和Constructor不是一个类了
正如List&T&和List不是一个类一样------解决方案--------------------你看看List&T&这样的泛型类构造函数是怎么定义的就知道了。
public&class&Constructor&T&
&&&&&&&&public&T&data&{&&&}
&&&&&&&&public&Constructor(T&t)
&&&&&&&&&&&&this.data&=&t;
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有C#的泛型的类型参数可以有带参数的构造函数的约束方式吗?Review后看到标题让我十分羞愧自己语文功底太差,估计...请见谅......我还特地把这句写回开头了......问题前天遇到的一个问题,所以在MSDN发了个问,刚也丰富了下问题,关于泛型的。最近用EF尝试DDD常常有些奇怪的想法,比如&EF的Model First能否添加泛型支持&。这次是&泛型的类型能否有带参数的约束方式&。具体想法很简单,在我使用泛型的时候,我发现我需要实例化一个类型参数:1 class MyClass&T&2 {3
public MyClass1()4
this.MyObject = new T();6
T MyObject { }9 }当然,上面会报错。错误内容是T没有一个new约束(new constraint),查阅下MSDN,得到了泛型的类型参数的new约束的内容。所以接下来正确的代码就是: 1 class MyClass&T& 2
where T : new() 3 { 4
public MyClass1() 5
this.MyObject = new T(); 7
T MyObject { }10 }然后,后来我发现,我需要根据参数来创建新的对象,而且该方法在泛型的构造函数中实现最合适,所以我希望有这样的代码: 1 class MyClass1&T& 2
where T : new(string) 3 { 4
public MyClass(string request) 5
this.MyObject = new T(request); 7
T MyObject { }10 }可惜这下就错大了,然后查阅泛型的约束方式列表,发现根本没有带参数的构造函数这种约束。所以就发生了我上面在MSDN上问的那个问题,寻求一个&优雅的解决方案&。一般解决方案就像问题中的回答那样有两种,也是我试过但是很不爽的两种,我们依次看看。补充:由James.Ying提醒,还有从构造函数传入由@Choo提醒,用Activator.CreateInstance工厂模式首先是Factory Pattern,就是建一个工厂类,先看看代码,这是其中一种写法,请不要纠结在Factory Pattern上: 1 class MyClass&T, TFactory& 2
where TFactory : IFactory&T&, new() 3 { 4
public MyClass(string request) 5
var factory = new TFactory(); 7
this.MyObject = factory.New(request); 9
T MyObject { }12 }13 14 interface IFactory&T&15 {16
T New(string request);17 }实现中你会发现,这样需要为每个派生类或者实例类别创建并维护一个Factory类,那样泛型本身就没那么大意义了,本来就是为了减少类型重用逻辑而采用泛型的。抽象基类的静态抽象方法如果不想维护多一个类,那么就在目标类本身下手,所以我们可以为目标类创建一个基类: 1 class MyClass&T& 2
where T : TBase, new() 3 { 4
public MyClass(string request) 5
this.MyObject = T.New(request); 7
T MyObject { }10 }11 12 abstract class TBase13 {14
public abstract static TBase New(string request);15 }为了防止误人子弟,首先要说在前头的是,这样写是会编译错误的!约束上是没错的,但是它报的错误是类似于&T是个类型参数,不能这么用!&('T' is a 'type parameter', which is not valid in the given context)。从构造函数传入还有一种基础的做法反而忘记了,由James.Ying提醒想起来,就是从泛型类的构造函数传入。class MyClass&T&
where T : TBase, new(){
public MyClass(T myObject)
this.MyObject = myO
T MyObject { }}这种方式使得泛型类简洁多了,把实例化的过程交给了调用者,有点依赖倒置了(其实凡是应该在泛型里实现的而交给了调用者或者继承者都是这样)。优点是泛型简单了,缺点就是你无法保证实例化使用的构造函数是T(string)。另外,它可能会降低代码的重用性。假设实例化是有条件地,而且所有派生类的逻辑是统一的,那么还是在泛型基类中实现比较好。简单情况下这是对泛型来说最优雅的方式了。Activator.CreateInstance该方法可以在/en-us/library/system.activator.createinstance(v=vs.110).x见到,说明就比较明确了:用最匹配的构造函数创建一个类型的实例(Creates an instance of the specified type using the constructor that best matches the specified parameters)。写法也很爽:class MyClass&T&{
public MyClass(string request)
this.MyObject = (T)Activator.CreateInstance(typeof(T), request);
T MyObject { }}这种方法做得到,也很简短,也不用多做接口和基类。缺点就是没有约束,没办法保证T能有带指定数量和类型参数的构造函数,或者是否有构造函数。如果T不符合设计需求的话会报相应的异常。原来泛型的类型参数是这么设计的至此,便可以知道,C#的泛型里,类型参数是一种&非类&的存在,类型参数的约束(Constraints on Type Parameters)仅仅是用来描述具体的类在实例化或者继承时所需要达到的条件。而在泛型内部,类型参数仅仅是一种&特别的存在&,它用来描述类,但却无法用作类。那么,类型参数可以有......参考本文题目......首先,其实这个问题本身就是泛型的类型参数能否有带参数的实例化方式,比如T myObject = new T("Hello World!&)。然后,由于类型参数是用&约束&的方式来进行实例类的特点的描述的,所以,问题才变成了泛型的类型参数能否有带参数的构造函数的约束方式,比如where T : new(string)。要做假设的话,起始就是个证伪的问题,要证明它存在是否会造成什么原则问题。首先能对比的就是泛型的类型参数已经有了不带参数的构造函数的约束方式了,那么泛型的类型参数就算有带了参数的构造函数的约束方式又如何?至少,泛型的类型参数已经有了不带参数的构造函数的约束方式证明了泛型的类型参数有构造函数的约束方式并不会造成什么问题而且技术上是可以实现的。(......)在我们实例化一个新对象的时候通常会用两种初始化方式:利用构造函数传参实例化后赋值大部分情况下两种方式产生的结果是差不多的,这种大部分情况是指一般所涉及到的属性或参数都是公开的(public),本来就是开放读写的,所以内部写和外部写都差不多。但遇到一些情况,比如一些业务约束,需要对参数进行处理或者利用参数进行操作,最终操作结果是私密的(ivate),那么就会偏向于选用构造函数传参。或者会使用一个特殊的方法,由该方法在类实例化之后再把需要的数据带进来进行操作,这么做些许有失&一气呵成&的爽快。利用构造函数传参并不是什么容易替代的方式,因为它在绝大部分属于它的场景里都是最优的解决方案。有时候,初始化一个对象到使用,一气呵成是最好的,因为这个事务本身就有很强的原子性。一个对象的两种初始化方式造成了双入口的麻烦,作为该类的使用者,有时候你会模糊,两种方式所产生的结果你无法准确地把握;对于开发者,两种实现方式供的出现在规范上也要求要么二选一,要么保证两者一致。当类变得相对复杂的时候,事情就没那么简单了。所以,我们确实会需要泛型的类型参数有带了参数的构造函数的约束方式的一些场景。它虽然不是必要的,但是绝对是一种需要,就像get/set访问器那样。补充地说,其实更大的命题是类型参数是否可以当作类使用假设它可以由带参数的构造函数约束了,那么可不可以直接如约束那样当作类来使用呢?比如调用静态方法?在泛型中创建继承于该类型参数的类?如此种种算来发现每一种都有可能是特例,而不是一个简单的实现即可解决的。比如调用静态方法来说,T.Hello()所涉及的就是执行的时候T能明确是哪个类;而在泛型类中创建继承于该类型参数的类就会变得复杂。单单想想调用那个类的方法:MyClass&T&.MySubClass,这里的语法就有点&不一般&了,未必是一个&仅仅是泛型本身的问题&。逼格高一点地说,越来越多的功能对C#或者任何一门语言来说是一条正确的道路吗?关于题目如果你有不满,可以提供合适的标题,禁止以任何方式攻击作者!
优质网站模板}

我要回帖

更多关于 泛型类的构造函数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信