当两个重载具有相同的签名时调用构造函数重载 [英] Calling constructor overload when both overload have same signature

查看:36
本文介绍了当两个重载具有相同的签名时调用构造函数重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下课程,

class Foo
{
    public Foo(int count)
    {
        /* .. */
    }

    public Foo(int count)
    {
        /* .. */
    }
}

以上代码无效,无法编译.现在考虑下面的代码,

Above code is invalid and won't compile. Now consider the following code,

class Foo<T>
{
    public Foo(int count)
    {
        /* .. */
    }

    public Foo(T t)
    {
        /* .. */
    }
}

static void Main(string[] args)
{
    Foo<int> foo = new Foo<int>(1);
}

以上代码有效且编译良好.它调用 Foo(int count).

Above code is valid and compiles well. It calls Foo(int count).

我的问题是,如果第一个无效,第二个如何有效?我知道 class Foo 是有效的,因为 T 和 int 是不同的类型.但是当它像 Foo 一样使用时foo = new Foo(1), T 正在获取整数类型并且两个构造函数都将具有相同的签名,对吗?为什么编译器不显示错误而不是选择一个重载来执行?

My question is, if the first one is invalid, how can the second one be valid? I know class Foo<T> is valid because T and int are different types. But when it is used like Foo<int> foo = new Foo<int>(1), T is getting integer type and both constructor will have same signature right? Why don't compiler show error rather than choosing an overload to execute?

推荐答案

在设计 C# 2.0 和 CLR 中的泛型类型系统时,您的问题引起了激烈的争论.如此火爆,事实上,A-W 发布的绑定"C# 2.0 规范实际上有错误的规则!有四种可能:

Your question was hotly debated when C# 2.0 and the generic type system in the CLR were being designed. So hotly, in fact, that the "bound" C# 2.0 specification published by A-W actually has the wrong rule in it! There are four possibilities:

1) 声明在某些构造下可能不明确的泛型类是非法的.(这是绑定规范错误地说的规则.)所以你的 Foo 声明将是非法的.

1) Make it illegal to declare a generic class that could POSSIBLY be ambiguous under SOME construction. (This is what the bound spec incorrectly says is the rule.) So your Foo<T> declaration would be illegal.

2) 以产生歧义的方式构造泛型类是非法的.声明 Foo 是合法的,构造 Foo 是合法的,但是构造 Foo 是非法的.

2) Make it illegal to construct a generic class in a manner which creates an ambiguity. declaring Foo<T> would be legal, constructing Foo<double> would be legal, but constructing Foo<int> would be illegal.

3) 使其全部合法并使用重载解析技巧来确定泛型或非泛型版本是否更好.(这就是 C# 实际所做的.)

3) Make it all legal and use overload resolution tricks to work out whether the generic or nongeneric version is better. (This is what C# actually does.)

4) 做一些我没有想到的事情.

4) Do something else I haven't thought of.

规则#1 是个坏主意,因为它使一些非常常见且无害的场景变得不可能.考虑例如:

Rule #1 is a bad idea because it makes some very common and harmless scenarios impossible. Consider for example:

class C<T>
{
  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 是个坏主意,所以我们取消了它.

You want that to be illegal just because C<Stream> is ambiguous? Yuck. Rule #1 is a bad idea, so we scrapped it.

不幸的是,事情并没有那么简单.IIRC CLI 规则说,允许实现拒绝作为实际上确实导致签名歧义的非法构造.也就是说,CLI 规则类似于规则 #2,而 C# 实际上实现了规则 #3.这意味着理论上可能会有合法的 C# 程序转化为非法代码,这是非常不幸的.

Unfortunately, it is not as simple as that. IIRC the CLI rules say that an implementation is allowed to reject as illegal constructions that actually do cause signature ambiguities. That is, the CLI rules are something like Rule #2, whereas C# actually implements Rule #3. Which means that there could in theory be legal C# programs that translate into illegal code, which is deeply unfortunate.

关于这些模棱两可如何让我们的生活变得悲惨的更多想法,这里有几篇我写的关于这个主题的文章:

For some more thoughts on how these sorts of ambiguities make our lives wretched, here are a couple of articles I wrote on the subject:

http://blogs.msdn.com/ericlippert/存档/2006/04/05/569085.aspx

http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx

这篇关于当两个重载具有相同的签名时调用构造函数重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆