通用方法和方法重载
方法重载允许我们定义许多具有相同名称但具有不同参数集的方法(因此具有相同的名称但签名不同)。
这两种方法是否超载?
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类声明首先应该是非法的,因为在某种意义上它有两个具有相同签名的方法,
MyMethod
和MyMethod
?
不,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
情况要糟糕得多。 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
强迫它运行第一个。
上述就是C#学习教程:通用方法和方法重载分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1010685.html