当两个重载具有相同的签名时,调用构造函数重载
考虑以下课程,
class Foo { public Foo(int count) { /* .. */ } public Foo(int count) { /* .. */ } }
上面的代码无效,不会编译。 现在考虑以下代码,
class Foo { public Foo(int count) { /* .. */ } public Foo(T t) { /* .. */ } } static void Main(string[] args) { Foo foo = new Foo(1); }
以上代码有效且编译良好。 它调用Foo(int count) 。
我的问题是,如果第一个无效,第二个如何有效? 我知道类Foo 是有效的,因为T和int是不同的类型。 但是当它像Foo foo = new Foo (1)一样使用时 ,T会得到整数类型,并且两个构造函数都具有相同的签名吗? 为什么编译器不显示错误而不是选择执行重载?
当设计C#2.0和CLR中的generics类型系统时,您的问题引起了激烈的争论。 事实上,由AW发布的“绑定”C#2.0规范实际上有错误的规则! 有四种可能性:
1)声明在某些构造下可能有歧义的generics类是非法的。 (这是绑定规范错误地说的规则。)所以你的Foo
声明是非法的。
2)以造成歧义的方式构造generics类是非法的。 声明Foo
是合法的,构造Foo
将是合法的,但构造Foo
将是非法的。
3)使一切合法并使用重载决议技巧来确定通用或非通用版本是否更好。 (这就是C#实际上做的。)
4)做一些我没有想到的事情。
规则#1是一个坏主意,因为它使一些非常常见且无害的场景变得不可能。 考虑例如:
class C { public C(T t) { ... } // construct a C that wraps a T public C(Stream state) { ... } // construct a C based on some serialized state from disk }
你想要那只是因为C
是不明确的? 呸。 规则#1是一个坏主意,所以我们废弃它。
不幸的是,它并不那么简单。 IIRC CLI规则规定允许实现拒绝实际导致签名含糊不清的非法构造。 也就是说,CLI规则类似于规则#2,而C#实际上实现了规则#3。 这意味着理论上可以将合法的C#程序转换为非法代码,这是非常不幸的。
关于这些歧义如何使我们的生活变得悲惨的更多想法,这里有几篇关于这个主题的文章:
https://blogs.msdn.com/ericlippert/archive/2006/04/05/569085.aspx
https://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
没有歧义,因为编译器将选择匹配的Foo(...)
的最具体的重载。 由于具有generics类型参数的方法被认为不如相应的非generics方法特定,因此当T == int
时, Foo(T)
不如Foo(int)
特异。 因此,您正在调用Foo(int)
重载。
你的第一种情况(有两个Foo(int)
定义)是一个错误,因为编译器只允许一个具有完全相同签名的方法的定义,并且你有两个。
Eric Lippert最近在博客上发表了这篇文章。
事实是,他们不是都有相同的签名 – 一个是使用generics而另一个不是。
使用这些方法,您还可以使用非int对象调用它:
上述就是C#学习教程:当两个重载具有相同的签名时,调用构造函数重载分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
Foo foo = new Foo ("Hello World");
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/997778.html