方法重载允许我们定义许多具有相同名称但具有不同参数集的方法(因此具有相同的名称但不同的签名).
这两种方法是否超载?
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
Run Code Online (Sandbox Code Playgroud)
编辑:
不应该声明A<int>.MyMethod(myInt);抛出错误,因为构造类型A<int>有两个具有相同名称和相同签名的方法?
Eri*_*ert 47
这两种方法是否超载?
是.
不应该声明
A<int>.MyMethod(myInt);抛出错误,因为构造类型A<int>有两个具有相同签名的方法?
这个问题没有意义; A您声明它不是通用类型.也许你打算问:
该语句是否
A.MyMethod(myInt);会导致编译器报告错误,因为有两种不明确的候选方法?
没有.正如其他人所说,在这种情况下,重载解析更喜欢非通用版本.请参阅下面的更多细节.
或许你想要问:
A类声明首先应该是非法的,因为在某种意义上它有两种具有相同签名的方法,
MyMethod并且MyMethod<int>?
不,A型是完全合法的.通用arity是签名的一部分.因此,没有两种方法具有相同的签名,因为第一种方法具有通用arity零,第二种方法具有通用arity one.
或许你想要问:
class G<T>
{
public static void M(T t) {}
public static void M(int t) {}
}
Run Code Online (Sandbox Code Playgroud)
G<T>可以构造泛型类型,使得它具有两个具有相同签名的方法.声明这种类型是否合法?
是的,声明这种类型是合法的.这通常是一个坏主意,但它是合法的.
然后你可以反驳:
但是我的Addison-Wesley发布的C#2.0规范副本在第479页声明"使用相同名称声明的两个函数成员...必须具有参数类型,这样任何封闭的构造类型都不能有两个具有相同名称的成员签名. "这有什么用?
当C#2.0最初被设计为计划时.然而,设计师意识到这种理想的模式将被视为非法:
class C<T>
{
public C(T t) { ... } // Create a C<T> from a given T
public C(Stream s) { ... } // Deserialize a C<T> from disk
}
Run Code Online (Sandbox Code Playgroud)
现在我们说抱歉伙伴,因为你可以说C<Stream>,导致两个施工人员统一,整个班级都是非法的.那将是不幸的.显然,任何人都不可能用Stream作为类型参数来构造这个东西!
不幸的是,在文本更新到最终版本之前,规范已经出版.第479页的规则不是我们实施的规则.
继续代表您提出更多问题:
那么如果你打电话
G<int>.M(123)或者在原始的例子中,如果你打电话A.MyMethod(123)会怎么样?
当重载决策面临两种由于通用结构而具有相同签名的方法时,那么通用结构的方法被认为是"不太具体"而不是"自然"的方法.一种不太具体的方法会失去更具体的方法.
那么,如果重载解析有效,为什么这是一个坏主意呢?
情况并A.MyMethod不太糟糕; 通常很容易明确地确定出哪种方法.但情况G<int>.M(123)要糟糕得多.CLR规则使这种情况"实现定义的行为",因此任何旧的事情都可能发生.从技术上讲,CLR可以拒绝验证构造类型的程序G<int>.或者它可能崩溃.事实上它既没有; 在糟糕的情况下,它能做到最好.
是否有这种类型结构的例子导致真正的实现定义行为?
是.有关详情,请参阅这些文章
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx