c# - 泛型方法和方法重载

标签 c# generics

方法重载允许我们定义许多具有相同名称但具有不同参数集的方法(因此具有相同的名称但不同的签名)。

这两个方法是否重载了?

class A
{
    public static void MyMethod<T>(T myVal) { }
    public static void MyMethod(int myVal) { }
}

编辑:

不应该声明A<int>.MyMethod(myInt);抛出错误,因为构造类型 A<int>有两个同名同签名的方法吗?

最佳答案

Are the two methods overloaded?

是的。

Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same signature?

这个问题没有意义; A不是您声明的通用类型。也许你想问:

Should the statement A.MyMethod(myInt); cause the compiler to report an error, since there are two ambiguous candidate methods?

没有。正如其他人所说,在这种情况下,重载解析更喜欢非泛型版本。有关更多详细信息,请参见下文。

或者你可能想问:

Should the declaration of type A be illegal in the first place, since in some sense it has two methods with the same signature, MyMethod and MyMethod<int>?

没有。 A型是完全合法的。 通用元数是签名的一部分。因此,不存在具有相同签名的两种方法,因为第一个具有通用元数 0,第二个具有通用元数 1。

或者你可能想问:

class G<T> 
{
    public static void M(T t) {}
    public static void M(int t) {}
}

Generic type G<T> can be constructed such that it has two methods with the same signature. Is it legal to declare such a type?

是的,声明这样的类型是合法的。这通常是一个坏主意,但它是合法的。

你可能会反驳:

But my copy of the C# 2.0 specification as published by Addison-Wesley states on page 479 "Two function members declared with the same names ... must have have parameter types such that no closed constructed type could have two members with the same name and signature." What's up with that?

最初设计 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
}

现在我们说抱歉,伙计,因为你可以说 C<Stream> ,导致两个构造函数统一,整个类不合法。那将是不幸的。很明显,任何人都不可能用 Stream 作为类型参数构造这个东西!

不幸的是,规范在文本更新为最终版本之前就已付印。第 479 页上的规则不是我们实现的。

继续代表您提出更多问题:

So what happens if you call G<int>.M(123) or, in the original example, if you call A.MyMethod(123)?

当重载解析面临两种由于泛型构造而具有相同签名的方法时,泛型构造的方法被认为比“自然”的方法“更不具体”。不太具体的方法输给了更具体的方法。

So why is it a bad idea, if overload resolution works?

A.MyMethod 的情况还不错;通常很容易明确地确定要使用哪种方法。但是G<int>.M(123)的情况更糟。 CLR 规则使这种情况成为“实现定义的行为”,因此任何旧事情都可能发生。从技术上讲,CLR 可以拒绝验证构造类型 G<int> 的程序。 .或者它可能会崩溃。事实上,它两者都没有;它会在糟糕的情况下尽力而为。

Are there any examples of this sort of type construction causing truly implementation-defined behaviour?

是的。有关详细信息,请参阅这些文章:

https://ericlippert.com/2006/04/05/odious-ambiguous-overloads-part-one/

https://ericlippert.com/2006/04/06/odious-ambiguous-overloads-part-two/

关于c# - 泛型方法和方法重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3679562/

相关文章:

java - 具有 super 泛型的代码无法按预期工作

arrays - Swift 4.1 中对类绑定(bind)协议(protocol)的弱引用的通用数组

haskell - 泛型中的约束类型

c# - 未将对象引用设置为对象的实例(将列表映射到自动映射器)

如果属性访问 C# Struct 方法不保存值

C#.NET 组合框控件

c++ - 为什么我们需要类型名称依赖于 C++ 中的模板参数

c# - 使用 JsonConvert.DeserializeObject 将 Json 反序列化为 C# POCO 类

c# - Visual Studio Community 2013 缺少 C# 添加新项目

java - 什么是原始类型,为什么我们不应该使用它呢?