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

Posted

技术标签:

【中文标题】C#中具有相同名称和签名但返回类型不同的方法【英文标题】:Method with same name and signature but different return type in C# 【发布时间】:2013-02-28 00:52:50 【问题描述】:

我在面试中被问到以下问题:

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

谁能告诉我以下内容:

    在任何情况下都可能出现上述情况(例如基类中的一个和派生类中的一个?)如果是,它是什么类型?比如编译或运行时多态?

    在编译时多态中,如果方法的返回类型和签名也不同怎么办?但只有函数的名称是相同的。还是编译时多态吗?

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

谢谢

【问题讨论】:

你的答案是什么,为什么? 不可能。您可以尝试以这种方式重载您的方法,但编译器不会接受。 @Oded:大声笑我才意识到我回答错了。我说过,它被称为编译时多态性,并且在同一个类中是不可能的,但是一个虚函数可以在基类中,我们可以覆盖它或在派生类中使用“new”关键字以不同的返回类型。但是如果我们把它放在同一个类中,它会给出一个错误,说两个函数有相同的名字。我在面试时没有深思熟虑,我才意识到:(哈哈这个我无法回答的简单问题,走了。我应该多做些工作。 @Nolonar:非常感谢您的回答,今晚我将在 VS 中处理所有可能的情况以很好地理解这一点......再次感谢您:) 干杯 【参考方案1】:

您可以使用dynamic 返回类型:

dynamic (C# Reference) Using Type dynamic (C# Programming Guide)

【讨论】:

【参考方案2】:

你可以在界面上做到这一点

   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());
    

【讨论】:

【参考方案3】:

我最近遇到了这个确切的问题,因为我正在解析具有各种类型的配置文件,这些类型都使用标准的 config.Parse(string settingName) 类型接口。

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

T Parse<T> (string settingName)

    T Result;
    doParsing...
    return T;

我不太喜欢这个,因为它涉及明确指定正在使用的类型,例如someSetting = Parse&lt;float&gt;("param");

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

T Parse<T> (string settingName, out T result)

    doParsing...
    return T;

out 变量和 return 是相同的,所以它有点多余,但它使我认为是一个更干净的接口:

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

您会获得仅因返回类型不同而有所不同的方法,这会带来轻微的冗余成本。最重要的是,如果您的数据类型发生变化,例如从双精度型变为浮点型,那么您一切都将继续正常工作,而使用第一个解决方案您最终会得到无法隐式转换错误。

【讨论】:

【参考方案4】:

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

只需按照下面的代码操作,它可能会对您有所帮助。

public class myClass

    public int myReturn()  return 123; 
    public string myReturn(string temp = null)  return "test"; 

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

【讨论】:

我不这么认为,它不会用“var x = myReturn();”编译【参考方案5】:

在 C# 中,你不能拥有像

这样的方法

int Foo() return 1;

void Foo() return;

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

如果参数不同,那么你就可以开始了。

int Foo(string x) return 1;

void Foo(double x) return;

【讨论】:

这完全让我明白了,非常感谢:) 干杯 顺便说一句,我在这里根本看不到多态性,但我没有参加你的采访。 :) 真正快速的多态性就像 void Foo(Animal a).. 和 class Dog : Animal。你用狗而不是动物来调用 Foo(aDog)。多态性将您的派生类型(Dog)神奇地转换为基本类型(Animal)。更多关于多态性的信息:codeproject.com/Articles/4839/Building-Snap-In-Applications 再次感谢托德,不知怎的,很多事情对我来说都是新事物,因为我已经 3 个月没有接触了。同样,我是一个初学者(我有大约 2 年的经验,还有很多东西要学)...谢谢 :) 我正在浏览这个 codeproject 链接 :) 干杯【参考方案6】:

由于这是一个面试问题,你可以稍微回答一下。

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

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

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

【讨论】:

感谢 gabnaim 的回答,这对我有帮助:)【参考方案7】:

我认为问题是关于return type covariance

它允许方法返回比在基类型中声明的类型更派生的类型,例如

public interface ISomeInterface

    object GetValue();


public class SomeClass : ISomeInterface

    public string GetValue()  return "Hello world"; 

这在 Java 中受支持,但在 C# 中不受支持。以上将无法编译,因为SomeClass.GetValue 的返回类型是string 而不是object

请注意,您不能仅基于返回类型重载方法,即以下内容无效:

public class SomeClass

    public int GetValue()  return 1; 
    public string GetValue()  return "abc"; 

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

public interface IValue<T>  T GetValue(); 
public class SomeClass : IValue<int>, IValue<string>

    string IValue<string>.GetValue()  return "abc"; 
    int IValue<int>.GetValue()  return 1; 

如果名称相同但参数不同,则这是方法重载。这是一种形式的多态性(ad-hoc polymorphism)。重载在 compile-type 静态解析(除非您使用 dynamic 在这种情况下它们被推迟到运行时)。

你可以重载参数的数量和它们的类型,所以以下都是有效的:

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

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

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

【讨论】:

谢谢,但在第二个问题中,我很想知道,当我们说方法重载时。就像,我们应该首先为方法使用相同的名称?其次,我们应该通过数字或类型来改变参数?最后我应该有相同的返回类型吗?否则程序根本无法编译,这就是你的意思吗? C# 中没有任何概念吗? @Divine - 重载时方法名称必须相同,但参数列表必须不同。它们的类型和/或参数数量可能不同。不需要具有相同的返回类型,只是重载解析仅对方法的参数进行,而不是返回类型。这意味着方法不能仅在其返回类型上被重载。我已经用这些信息更新了答案。 C# 确实允许方法重载,但不允许基于返回类型重载方法,并且不允许返回类型协变。 非常感谢,正如托德所说, public int DoSomething(string value) public void DoSomething(int value, string value) 我可以这样吗?没问题 ?但是我知道它不会超载【参考方案8】:

虽然 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() 的最终结果是它将始终匹配最具体的可用类型。

【讨论】:

感谢 Jean 向我解释,这对我有帮助 :) 干杯【参考方案9】:

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

public interface I 
  int foo();


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

【讨论】:

以上是关于C#中具有相同名称和签名但返回类型不同的方法的主要内容,如果未能解决你的问题,请参考以下文章

C#委托初学

具有相同名称但参数和返回类型不同的虚拟函数[重复]

15-多态

为啥 C# 在多态中不考虑函数的返回类型?

C# 方法签名以及怎样的两个方法才算是不同的方法

如何反序列化具有相同名称但不同类型的 API 响应