我接受了一次采访,我被问到如下:
问题:具有相同名称和签名但返回类型不同的方法。是否有可能,他问我这种类型的是什么。
有人可以告诉我以下内容:
在任何情况下都可以上面的东西(比如基类中的一个和至少派生类中的一个?)如果是这样的话是什么类型的?像编译或运行时多态?
在编译时多态性中,如果方法的返回类型与签名不同,该怎么办?但只有功能名称相同。是编译时多态吗?
在覆盖中,如果我有不同的返回类型但方法名称和签名相同怎么办?可能吗 ? (他问我这个问题,我回答错误:()请帮助我。
谢谢
答案 0 :(得分:33)
它允许方法返回比在基类型中声明的类型更多派生的类型,例如
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> { T GetValue(); }
public class SomeClass : IValue<int>, IValue<string>
{
string IValue<string>.GetValue() { return "abc"; }
int IValue<int>.GetValue() { return 1; }
}
如果名称相同但参数不同则这是方法重载。这是一种多态性(ad-hoc多态性)。在编译类型下静态解析重载(除非您使用dynamic
,在这种情况下,它们将延迟到运行时)。
您可以重载参数数量及其类型,因此以下各项均有效:
public void DoSomething(int value) { }
public void DoSomething(string value) { }
public void DoSomething(int value, string value) { }
请注意,您可以改变这些方法的返回类型 - 方法不仅可以根据其返回类型单独重载,而且如果参数列表不同,它们可能会有所不同。
这又是返回类型协方差,在C#中不受支持。
答案 1 :(得分:10)
在C#中,你不能拥有像
这样的方法 int Foo() { return 1; }
void Foo() { return; }
它们的变化必须超过返回类型。
如果争论不同,那么你就可以去了。
int Foo(string x) { return 1; }
void Foo(double x) { return; }
答案 2 :(得分:7)
虽然C#不支持返回类型协方差,但可以通过使用显式实现和方法隐藏来模拟它。这是一种在ADO.NET API中彻底使用的模式。
E.g:
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()
的最终结果是它将始终匹配最具体的可用类型。
答案 3 :(得分:6)
是的,使用显式接口实现可以使多个方法具有相同的签名但返回类型不同,如下所示:
public interface I {
int foo();
}
public class C : I {
double foo() { return 2.0; }
int I.foo() { return 4; }
}
答案 4 :(得分:2)
由于这是一个面试问题,你可以稍微运行一下你的答案。
严格地说,不可能使用具有不同返回类型和相同签名的方法。但是,从广义上讲,有很多方法可以实现具体运行时返回类型不同的方法。
一个是使用通用参数。另一个是返回具有多个实现的接口或超类。或者,您可以返回一个对象,可以将其转换为任何对象。
正如许多人提到的,您还可以使用“new”关键字在子类中返回相同方法的派生类型。
答案 5 :(得分:0)
是的,您可以使用相同的方法,相同的参数(需要自定义)和不同的返回值。
只需按照以下代码,它就可以为您提供帮助。
public class myClass
{
public int myReturn() { return 123; }
public string myReturn(string temp = null) { return "test"; }
}
事实上,它需要参数来执行函数,但是你仍然能够忽略参数,因为你有string temp = null
作为可选参数,你仍然可以使用或不使用参数来调用函数。 / p>
答案 6 :(得分:0)
我最近遇到了这个问题,因为我正在使用各种类型解析配置文件,这些类型都使用标准的config.Parse(string settingName)类型接口。
第一种解决方案通用方法:
T Parse<T> (string settingName)
{
T Result;
doParsing...
return T;
}
我真的不喜欢这个,因为它涉及明确指定正在使用的类型,例如someSetting = Parse<float>("param");
所以我使用的解决方案是多余的,但在我看来更干净:
T Parse<T> (string settingName, out T result)
{
doParsing...
return T;
}
out变量和返回值是相同的,所以它有点多余,但它可以实现我认为更清晰的界面:
setting = Parse("intparam", out setting);
并且您获得的方法仅根据返回类型而有所不同,以获得轻微的冗余成本。最重要的是,如果您的数据类型发生变化,例如从double变为float,那么您所有内容都将继续正常工作,而使用第一个解决方案时,您最终无法隐式转换错误。
答案 7 :(得分:0)
您可以使用dynamic
返回类型:
答案 8 :(得分:-1)
你可以使用白色界面
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());
}