C#中具有相同名称和签名但返回类型不同的方法

我接受了一次采访,询问了以下情况:

问题:具有相同名称和签名但返回类型不同的方法。 是否有可能,他问我这种类型是什么。

有人可以告诉我以下内容:

  1. 在任何情况下都是可能的事情(比如基类中的一个和至少派生类中的一个?)如果是这样的类型是什么? 像编译或运行时多态?

  2. 在编译时多态,如果返回类型的方法也与签名不同怎么办? 但只有function名称相同。 是编译时多态吗?

  3. 在覆盖中,如果我有不同的返回类型但方法名称和签名相同怎么办? 可能吗 ? (他问我这个问题,我回答错误:()请帮帮我。

谢谢

  • 我假设问题是关于返回类型协方差
  • 它允许方法返回比在基类型中声明的类型更多派生的类型,例如

    public interface ISomeInterface { object GetValue(); } public class SomeClass : ISomeInterface { public string GetValue() { return "Hello world"; } } 

    这在Java中受支持,但在C#中不受支持。 由于SomeClass.GetValue的返回类型是string而不是object因此上面不会编译。

    请注意,您不能仅基于return-type重载方法,即以下内容无效:

     public class SomeClass { public int GetValue() { return 1; } public string GetValue() { return "abc"; } } 

    你可以使用接口做类似的事情,尽管你需要明确地实现它们以消除歧义:

     public interface IValue { T GetValue(); } public class SomeClass : IValue, IValue { string IValue.GetValue() { return "abc"; } int IValue.GetValue() { return 1; } } 
  • 如果名称相同但参数不同则这是方法重载。 这是一种多态性(ad-hoc多态性)。 在编译类型下静态解析重载(除非您使用dynamic在这种情况下,它们被延迟到运行时)。

    您可以重载参数的数量及其类型,因此以下都是有效的:

     public void DoSomething(int value) { } public void DoSomething(string value) { } public void DoSomething(int value, string value) { } 

    请注意,您可以改变这些方法的返回类型 – 方法不仅可以根据其返回类型单独重载,而且如果参数列表不同,它们可能会有所不同。

  • 这又是返回类型协方差,在C#中不受支持。

    在C#中,你不能有类似的方法

    int Foo() { return 1; }

    void Foo() { return; }

    它们的变化必须超过返回类型。

    如果争论不同,那么你很高兴。

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    虽然C#不支持返回类型协方差,但可以通过使用显式实现和方法隐藏来模拟它。 这是在ADO.NET API中彻底使用的模式。

    例如:

     public interface ISomeValue { } public abstract class SomeValueBase : ISomeValue { } public class SomeValueImpl : SomeValueBase { } public interface ISomeObject { ISomeValue GetValue(); } public abstract class SomeObjectBase : ISomeObject { ISomeValue ISomeObject.GetValue() { return GetValue(); } public SomeValueBase GetValue() { return GetValueImpl(); } protected abstract SomeValueBase GetValueImpl(); } public class SomeObjectImpl : SomeObjectBase { protected override SomeValueBase GetValueImpl() { return GetValue(); } public new SomeValueImpl GetValue() { return null; } } 

    通过这样做,调用GetValue()的最终结果是它将始终匹配最具体的可用类型。

    是的,使用显式接口实现可以使多个方法具有相同的签名但返回类型不同,如下所示:

     public interface I { int foo(); } public class C : I { double foo() { return 2.0; } int I.foo() { return 4; } } 

    由于这是一个面试问题,你可以稍微运行一下你的答案。

    严格地说,不可能使用具有不同返回类型和相同签名的方法。 但是,从广义上讲,实现具体运行时返回类型变化的方法有很多种方法。

    一个是使用通用参数。 另一个是返回具有多个实现的接口或超类。 或者,您可以返回一个可以强制转换为任何对象的对象。

    正如许多人提到的,您还可以使用“new”关键字在子类中返回相同方法的派生类型。

    是的,您可以使用相同的方法,相同的参数(需要自定义)和不同的返回值。

    只需按照以下代码,它可能会对您有所帮助。

     public class myClass { public int myReturn() { return 123; } public string myReturn(string temp = null) { return "test"; } } 

    问题是,它需要参数来执行函数,但是你仍然可以忽略参数,因为你有string temp = null作为可选参数,你仍然可以使用或不使用参数调用函数。

    我最近遇到了这个问题,因为我正在解析一个配置文件,其中包含各种类型的配置文件,它们都使用标准的config.Parse(string settingName)类型接口。

    第一种解决方案通用方法:

     T Parse (string settingName) { T Result; doParsing... return T; } 

    我真的不喜欢这个,因为它涉及显式指定正在使用的类型,例如someSetting = Parse("param");

    所以我使用的解决方案是多余的,但在我看来更干净:

     T Parse (string settingName, out T result) { doParsing... return T; } 

    out变量和返回是相同的,所以它有点多余,但它使我认为是一个更清洁的界面:

     setting = Parse("intparam", out setting); 

    并且您获得的方法仅根据返回类型而有所不同,以获得轻微的冗余成本。 最重要的是,如果您的数据类型发生变化,例如从double变为float,那么您所有内容都将继续正常工作,而使用第一个解决方案时,您最终无法隐式转换错误。

    您可以使用dynamic返回类型:

    • 动态(C#参考)
    • 使用Type动态(C#编程指南)

    你可以做whit接口

      public interface IMyInterface { int Metoda1()enter code here`; } public class MyClass : test.IMyInterface { public IMyInterface Metoda1() { return new MyClas(); } int test.IMyInterface.Metoda1() { return 1; } } static void Main(string[] args) { MyClass instance = new MyClass(); IMyInterface inst = instance.Metoda1(); /* IMyInterface ints2 = inst.Metoda1(); //will not compile*/ Console.WriteLine(inst.GetType().ToString()); ; object inst3 = inst.Metoda1(); Console.WriteLine(inst3.GetType().ToString()); }