为什么 C# 不支持类构造函数中隐含的泛型类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why doesn't C# support implied generic types on class constructors?
提问by Keith
C# doesn't require you to specify a generic type parameter if the compiler can infer it, for instance:
如果编译器可以推断,C# 不需要您指定泛型类型参数,例如:
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();
This is needed for anonymous types where you don't know what the type parameter would be (in intellisense it shows up as 'a
) because it's added by the compiler.
对于您不知道类型参数是什么(在智能感知中它显示为'a
)的匿名类型,这是必需的,因为它是由编译器添加的。
Class-level type parameters don't let you do this:
类级类型参数不允许您这样做:
//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 );
Why doesn't C# support this class level generic type inference?
为什么 C# 不支持此类级别的泛型类型推断?
采纳答案by Konrad Rudolph
Actually, your question isn't bad. I've been toying with a generic programming language for last few years and although I've never come around to actually develop it (and probably never will), I've thought a lot about generic type inference and one of my top priorities has always been to allow the construction of classes without having to specify the generic type.
事实上,你的问题并不坏。过去几年我一直在研究泛型编程语言,虽然我从未真正开发它(可能永远不会),但我对泛型类型推断进行了很多思考,我的首要任务之一是一直允许在不必指定泛型类型的情况下构造类。
C# simply lacks the set of rules to make this possible. I think the developers never saw the neccesity to include this. Actually, the following code would be very near to your proposition and solve the problem. All C# needs is an added syntax support.
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);
Since this code actually works, we've shown that the problem is not one of semantics but simply one of lacking support. I guess I have to take back my previous posting. ;-)
由于这段代码实际上有效,我们已经证明问题不是语义之一,而只是缺乏支持之一。我想我必须收回我以前的帖子。;-)
回答by Konrad Rudolph
Why doesn't C# support this class level generic type inference?
为什么 C# 不支持此类级别的泛型类型推断?
Because they're generally ambiguous. By contrast, type inference is trivial for function calls (if all types appear in arguments). But in the case of constructor calls (glorified functions, for the sake of discussion), the compiler has to resolve multiple levels at the same time. One level is the class level and the other is the constructor arguments level. I believe solving this is algorithmically non-trivial. Intuitively, I'd say it's even NP-complete.
因为它们通常是模棱两可的。相比之下,类型推断对于函数调用来说是微不足道的(如果所有类型都出现在参数中)。但是在构造函数调用(美化函数,为了讨论)的情况下,编译器必须同时解析多个级别。一个级别是类级别,另一个级别是构造函数参数级别。我相信解决这个问题在算法上是非常重要的。直觉上,我会说它甚至是 NP 完全的。
To illustrate an extreme case where resolution is impossible, imagine the following class and tell me what the compiler should do:
为了说明无法解析的极端情况,请想象以下类并告诉我编译器应该做什么:
class Foo<T> {
public Foo<U>(U x) { }
}
var x = new Foo(1);
回答by Keith
Thanks Konrad, that's a good response (+1), but just to expand on it.
谢谢康拉德,这是一个很好的回应(+1),但只是为了扩展它。
Let's pretend that C# has an explicit constructor function:
让我们假设 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
You're quite right that the first constructor can't be inferred.
您说得对,无法推断出第一个构造函数。
Now let's go back to the class
现在让我们回到课堂
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 );
Of course, if I add your constructor back in (with its alternate type) we have an ambiguous call - exactly as if a normal method overload couldn't be resolved.
当然,如果我重新添加您的构造函数(及其替代类型),我们会产生一个模棱两可的调用 - 就像无法解析正常的方法重载一样。