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

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

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

谁能告诉我以下内容:

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

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

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

谢谢

【问题讨论】:

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

标签: c# .net c#-4.0 inheritance polymorphism


【解决方案1】:

您可以使用dynamic 返回类型:

【讨论】:

    【解决方案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; }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-09
          • 1970-01-01
          • 1970-01-01
          • 2013-02-23
          相关资源
          最近更新 更多