Метод с тем же именем и сигнатурой, но возвращаемый тип в С#
У меня было интервью, где меня спросили следующее:
Вопрос: метод с тем же именем и подписями, но с другим возвращаемым типом. Возможно ли это, и что это такое? Он спросил меня.
Может кто-нибудь скажет мне следующее:
-
Возможно ли это в любых сценариях (как в базовом классе, так и в производном классе по крайней мере?) Если да, то какой это тип? Как полиморфизм компиляции или времени выполнения?
-
Во время полиморфизма времени компиляции, что, если возвращаемые типы методов также различаются вместе с сигнатурой? Но только имя функции такое же. До сих пор ли он компилирует полиморфизм?
-
В переопределении, что, если у меня есть другой тип возврата, но имя метода и подпись такие же? Является ли это возможным? (Он задал мне этот вопрос, я ответил не так:() Пожалуйста, помогите мне.
Спасибо
Ответы
Ответ 1
Я предполагаю, что речь идет о ковариации возвращаемого типа
Он позволяет методу возвращать более производный тип, чем тот, который объявлен в базовом типе, например.
public interface ISomeInterface
{
object GetValue();
}
public class SomeClass : ISomeInterface
{
public string GetValue() { return "Hello world"; }
}
Это поддерживается в Java, но не в С#. Вышеупомянутое не будет компилироваться, так как тип возврата SomeClass.GetValue
равен string
not 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) { }
Обратите внимание, что вы можете изменить тип возвращаемого значения этих методов - методы могут не только перегружаться только на основе их типа возврата, но они могут различаться, если их списки параметров различны.
Опять же, это ковариация типа возврата и не поддерживается в С#.
Ответ 2
В С# у вас не могут быть такие методы, как
int Foo() { return 1; }
void Foo() { return; }
Они должны отличаться от типа возврата.
Если аргументы разные, тогда вам хорошо идти.
int Foo(string x) { return 1; }
void Foo(double x) { return; }
Ответ 3
Хотя ковариация типа возврата не поддерживается в С#, ее можно эмулировать с помощью явной реализации и скрытия метода. Это шаблон, который полностью используется в API ADO.NET.
например:.
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()
заключается в том, что он всегда будет соответствовать наиболее доступному типу.
Ответ 4
Да, возможно иметь несколько методов с одной и той же сигнатурой, но с разными типами возвращаемых данных, используя реализацию Явного Интерфейса, как показано ниже:
public interface I {
int foo();
}
public class C : I {
double foo() { return 2.0; }
int I.foo() { return 4; }
}
Ответ 5
Так как это вопрос интервью, вы можете немного поговорить с ним.
Строго говоря, метод с другим типом возврата и одной и той же сигнатурой невозможен. Однако, в широком смысле, существует множество способов реализации метода, чей конкретный тип возвращаемого времени выполнения изменяется.
Один использует общие параметры. Другой возвращает интерфейс или суперкласс с несколькими реализациями. Или вы можете вернуть объект, который может быть применен к чему-либо.
Как уже упоминалось, вы также можете использовать "новое" ключевое слово для возврата производного типа того же метода в подкласс.
Ответ 6
да, вы можете использовать один и тот же метод, те же параметры (необходимо настроить) и разные возвращаемые значения.
Просто следуйте приведенным ниже кодам, это может вам помочь.
public class myClass
{
public int myReturn() { return 123; }
public string myReturn(string temp = null) { return "test"; }
}
вещь, она требует, чтобы параметр выполнял функции, но вы все еще можете игнорировать параметры, поскольку у вас есть string temp = null
в качестве дополнительных параметров, которые вы все еще вызываете функциями с параметрами или без них.
Ответ 7
Недавно у меня была эта точная проблема, так как я разбирал конфигурационный файл с различными типами, которые используют стандартный тип интерфейса 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;
}
Выходная переменная и возврат идентичны, поэтому она немного избыточна, но она обеспечивает то, что я считаю намного более понятным интерфейсом:
setting = Parse("intparam", out setting);
И вы получаете методы, которые меняются только по типу возврата для небольшой стоимости избыточности. Кроме того, если тип ваших данных изменяется, например, с двойного на float, тогда вы все будете работать нормально, тогда как с первым решением, которое вы получите, не может неявно преобразовывать ошибки.
Ответ 8
Вы можете использовать возвращаемый тип dynamic
:
Ответ 9
Вы можете сделать это с интерфейсом
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());
}