2013-03-12 79 views
18

我有一次采访我在那里提出以下:方法具有相同名称和签名,但返回类型在C#

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

是否有人可以告诉我下面的:

  1. 是上面的事情,可能在任何情况下(就像一个基类,一个在派生类中ATLEAST?)如果是的话是什么类型呢?像编译或运行时多态?

  2. 在编译时多态性,如果方法的返回类型与签名一样也不同?但只有功能的名称是相同的。编译时多态性仍然是?

  3. 在重载,如果我有不同的返回类型,但方法名称和签名是相同的?可能吗 ? (他问我这个问题,我回答错:()请大家帮帮我。

谢谢

+7

什么_your_答案,为什么? – Oded 2013-03-12 13:21:57

+3

这是不可能的。你可以尝试以这种方式重载你的方法,但编译器不会接受。 – Nolonar 2013-03-12 13:22:07

+0

@Oded:lol我只是意识到我回答不正确。我说,它被称为编译时多态,在同一个类中它是不可能的,但是一个虚函数可以在基类中,我们可以覆盖它,或者在具有不同返回类型的派生类中使用“新”关键字。但是,如果我们在同一个班上有这个功能,它会给出一个错误说,两个功能具有相同的名称。我在采访时并没有体贴周到,我只是意识到:(大声笑这个简单的问题,我无法回答,走了,我应该更多的工作 – Learner 2013-03-12 13:31:56

回答

30

  • 我认为问题是关于return type covariance

    它允许一个方法返回一个更衍生型比在碱例如类型中声明的一个

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

    这在Java,但不是在C#支撑。上述将不编译的sinc e返回类型SomeClass.GetValuestring而不是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多态性)。重载可以在编译时静态解析(除非你使用dynamic,在这种情况下,它们被延迟到运行时)。

    您可以在参数的数量和它们的种类过,所以下面都是有效的:

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

    注意,你可以改变这些方法的返回类型 - 方法不仅可以重载基于它们的返回类型,但如果参数列表不同,它们可能会有所不同。

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

  • +0

    谢谢,但在第二个问题,我很想知道,当我们说一个方法是超载。比如,我们应该首先为该方法命名?其次,我们应该通过数字或类型来改变参数?最后,我应该有相同的返回类型吗?否则程序根本无法编译,那是什么意思? C#中的概念没有在这个权利? – Learner 2013-03-12 13:42:00

    +0

    @Divine - 重载方法名称时必须相同,但参数列表必须不同。它们可以在参数的类型和/或数量上有所不同。不需要具有相同的返回类型,只是重载解析仅在方法的参数上完成,而不是返回类型。这意味着方法不能单独在返回类型上重载。我已经用这些信息更新了答案。 C#允许方法重载,但不允许基于返回类型重载方法,并且不允许返回类型协方差。 – Lee 2013-03-12 13:55:48

    +0

    非常感谢,正如Todd所说的,public int DoSomething(string value){} public void DoSomething(int value,string value){}我可以有这个权利吗?没问题 ?但我明白它不会超载 – Learner 2013-03-12 14:08:59

    10

    int Foo() { return 1; }

    void Foo() { return; }

    在C#中,你不能有方法,他们必须比返回类型更多变化。

    如果参数不同,那么你很好走。

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    +0

    这完全让我明白,非常感谢你:)干杯 – Learner 2013-03-12 13:43:43

    +0

    顺便说一句,我没有看到多态在这里,但我没有坐在你的采访。 :)真正的快速,多态会像void Foo(Animal a){..}和class Dog:Animal {}。你用狗不是动物叫Foo(aDog)。多态性可以从派生类型(Dog)到基类型(Animal)进行魔术转换。更多的信息在这里多形态:http://www.codeproject.com/Articles/4839/Building-Snap-In-Applications – 2013-03-12 13:48:56

    +0

    再次谢谢托德,不知何故很多事情对我来说是新的,因为我没有触及3现在几个月。再次我是一个初学者(大约2年的经验,我仍然学习很多)...谢谢:)我正在通过这个codeproject链接:)干杯 – Learner 2013-03-12 14:03:50

    5

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

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

    谢谢皮特:)它是一个很好的信息:)干杯 – Learner 2013-03-12 13:44:46

    6

    虽然返回类型协方差在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()的最终结果是,它总是会匹配最具体的可用类型。

    +0

    谢谢吉恩解释我,它可以帮助我:)干杯 – Learner 2013-03-12 14:10:08

    +0

    非常有帮助的例子,谢谢! – Learner 2015-01-12 16:41:03

    2

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

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

    一个使用通用参数。另一种方法是返回一个具有多个实现的接口或超类。或者,您可以返回一个可以投射到任何物体的物体。

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

    +0

    谢谢你gabnaim的答案,这有助于我:) – Learner 2013-03-13 08:43:59

    0

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

    只要按照下面的代码,它可能会帮助你。

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

    的事情是,它需要的参数,使执行的功能,但你仍然可以,因为你有string temp = null作为可选参数,这是你还是叫功能带或不带参数忽略的参数。

    +0

    我不这么认为,它不会编译“var x = myReturn();” – 2018-01-24 00:57:07

    0

    我最近有这个确切的问题,因为我解析了一个配置文件,使用各种类型的全部使用标准的config.Parse(string settingName)类型的接口。

    1解决方案的通用方法:

    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变量和返回是相同的所以这是一个有点多余,但它使我瘦k是一个更简洁的界面:

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

    ,你会得到返回类型为冗余轻微的成本只有变化的方法。最重要的是,如果你的数据类型发生了变化,例如从双精度到浮点数,那么你的所有事情都会继续正常工作,而第一个解决方案最终会得到不能隐式转换错误的结果。

    -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()); 
        } 
    
    相关问题