Csharp/C#教程:通用方法和方法重载分享


通用方法和方法重载

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

这两种方法是否超载?

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

编辑:

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

这两种方法是否超载?

是。

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

这个问题没有意义; A不是您声明的generics类型。 也许你打算问:

应该是声明A.MyMethod(myInt); 导致编译器报告错误,因为有两个不明确的候选方法?

没有。正如其他人所说,在这种情况下,重载解析更喜欢非通用版本。 请参阅下面的更多细节。

或许你想要问:

A类声明首先应该是非法的,因为在某种意义上它有两个具有相同签名的方法, MyMethodMyMethod

不,A型是完全合法的。 通用arity是签名的一部分 。 因此,没有两种方法具有相同的签名,因为第一种方法具有通用arity零,第二种方法具有通用arity one。

或许你想要问:

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

可以构造通用类型G ,使得它具有两个具有相同签名的方法。 声明这种类型是否合法?

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

然后你可以反驳:

但是我的Addison-Wesley发布的C#2.0规范副本在第479页声明“使用相同名称声明的两个函数成员…必须具有参数类型,这样任何闭合构造类型都不能有两个具有相同名称的成员签名。 “那是怎么回事?

当C#2.0最初被设计为计划时。 然而,设计师意识到这种理想的模式将被视为非法:

 class C { public C(T t) { ... } // Create a C from a given T public C(Stream s) { ... } // Deserialize a C from disk } 

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

不幸的是,在文本更新到最终版本之前,规范已经出版。 第479页的规则不是我们实施的规则。

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

那么如果你调用G.M(123)或者在原始示例中调用A.MyMethod(123)什么?

当重载决策面临两种由于通用构造而具有相同签名的方法时,那么通用构造的方法被认为是“不太具体”而不是“自然”的方法。 一种不太具体的方法会失去更具体的方法。

那么,如果重载解析有效,为什么这是一个坏主意呢?

A.MyMethod的情况并不太糟糕; 通常很容易明确地确定出哪种方法。 但是G.M(123)情况要糟糕得多。 CLR规则使这种情况“实现定义的行为”,因此任何旧的事情都可能发生。 从技术上讲,CLR可以拒绝validation构造类型G 。 或者它可能崩溃。 事实上它既没有; 在糟糕的情况下,它能做到最好。

是否有任何这种类型构造的例子导致真正的实现定义行为?

是。 有关详情,请参阅这些文章

https://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx

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

是。 当参数的类型为int ,将调用MyMethod(int myVal) ,即使参数参数可隐式转换为硬编码类型(或者是派生类),也将为所有其他参数参数调用generics重载。 重载决策将最佳匹配,并且generics重载将在编译时解析为完全匹配。

注意:您可以显式调用generics重载并通过在方法调用中提供type参数来使用int ,正如Steven Sudit在他的回答中指出的那样。

 short s = 1; int i = s; MyMethod(s); // Generic MyMethod(i); // int MyMethod((int)s); // int MyMethod(1); // int MyMethod(1); // Generic** MyMethod(1.0); // Generic // etc. 

对,他们是。 他们将允许代码:

 A.MyMethod("a string"); // calls the generic version A.MyMethod(42); // calls the int version 

是的,他们超载了。 如果可用,编译器应该优先使用针对generics方法的显式方法签名。 但要注意,如果你可以避免这种过载,你可能应该这样做。 有关于这种过载和意外行为的错误报告。

https://connect.microsoft.com/VisualStudio/feedback/details/522202/c-3-0-generic-overload-call-resolution-from-within-generic-function

是。 它们具有相同的名称“MyMethod”但具有不同的签名。 但是,C#规范专门处理这个问题,因为当两者都是选项时,编译器会优先选择非generics版本而不是generics版本。

是。 如果你打电话给A.MyMethod(1); ,我的头顶A.MyMethod(1); ,它将始终运行第二种方法。 你必须打电话给A.MyMethod(1); 强迫它运行第一个。

上述就是C#学习教程:通用方法和方法重载分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/1010685.html

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

精彩推荐