Csharp/C#教程:当两个重载具有相同的签名时,调用构造函数重载分享


当两个重载具有相同的签名时,调用构造函数重载

考虑以下课程,

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

(0)
上一篇 2021年12月26日
下一篇 2021年12月26日

精彩推荐