为什么C#不支持类构造函数中的genericstypes?
如果编译器可以推断它,C#不要求你指定一个genericstypes参数,例如:
List<int> myInts = new List<int> {0,1,1, 2,3,5,8,13,21,34,55,89,144,233,377, 610,987,1597,2584,4181,6765}; //this statement is clunky List<string> myStrings = myInts. Select<int,string>( i => i.ToString() ). ToList<string>(); //the type is inferred from the lambda expression //the compiler knows that it's taking an int and //returning a string List<string> myStrings = myInts. Select( i => i.ToString() ). ToList();
这是匿名types所需要的,你不知道types参数是什么(在intellisense中显示为'a
),因为它是由编译器添加的。
类级别的types参数不会让你这样做:
//sample generic class public class GenericDemo<T> { public GenericDemo ( T value ) { GenericTypedProperty = value; } public T GenericTypedProperty {get; set;} } //why can't I do: int anIntValue = 4181; var item = new GenericDemo( anIntValue ); //type inference fails //however I can create a wrapper like this: public static GenericDemo<T> Create<T> ( T value ) { return new GenericDemo<T> ( value ); } //then this works - type inference on the method compiles var item = Create( anIntValue );
为什么C#不支持这个类级别的genericstypes推断?
其实你的问题不错 过去几年来我一直在使用generics编程语言,虽然我从来没有实际开发它(可能永远也不会),但我对genericstypes推断有很多想法,而且我的首要任务之一是总是允许build立类而不必指定通用types。
C#只是缺乏一套规则来实现这一点。 我认为开发者从来没有看到包括这个的必要性。 其实,下面的代码会非常接近你的主张并解决问题。 所有的C#需求都是一个附加的语法支持。
class Foo<T> { public Foo(T x) { … } } // Notice: non-generic class overload. Possible in C#! class Foo { public static Foo<T> ctor<T>(T x) { return new Foo<T>(x); } } var x = Foo.ctor(42);
由于这个代码实际上起作用了,我们已经certificate这个问题不是语义上的问题,而是缺乏支持的问题之一。 我想我必须收回我之前的发帖。 😉
为什么C#不支持这个类级别的genericstypes推断?
因为他们通常是模棱两可的。 相比之下,types推断对于函数调用来说是微不足道的(如果所有types都出现在参数中)。 但是在构造函数调用的情况下(为了讨论的缘故,函数是光荣的),编译器必须同时parsing多个级别。 一个级别是类级别,另一个级别是构造函数参数级别。 我相信解决这个问题在algorithm上是不平凡的。 直觉上,我会说这甚至是NP-complete。
为了说明解决不可能的极端情况,请想象下面的类,告诉我编译器应该做什么:
class Foo<T> { public Foo<U>(U x) { } } var x = new Foo(1);
感谢Konrad,这是一个很好的回应(+1),但只是为了扩大它。
让我们假装C#有一个显式的构造函数:
//your example var x = new Foo( 1 ); //becomes var x = Foo.ctor( 1 ); //your problem is valid because this would be var x = Foo<T>.ctor<int>( 1 ); //and T can't be inferred
你是对的,第一个构造函数不能被推断。
现在让我们回到课堂上
class Foo<T> { //<T> can't mean anything else in this context public Foo(T x) { } } //this would now throw an exception unless the //typeparam matches the parameter var x = Foo<int>.ctor( 1 ); //so why wouldn't this work? var x = Foo.ctor( 1 );
当然,如果我把你的构造函数添加回来(用它的替代types),我们有一个模棱两可的调用 – 就好像正常的方法重载不能被parsing一样。