Подтвердить что ты не робот

С# Возвращать разные типы?

У меня есть что-то вроде этого:

public [What Here?] GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return radio; or return computer; or return hello //should be possible?!      
}

У меня есть метод, и этот метод возвращает мне иногда разные типы значений (классы).

Как я могу это сделать в любом случае и, конечно же, позже работать с переменными, b.e radio.Play(); и до сих пор?

Нужно ли использовать дженерики? Как?

4b9b3361

Ответ 1

Если нет общего базового типа или интерфейса, тогда public object GetAnything() {...} - но обычно предпочтительнее иметь какую-то абстракцию, такую ​​как общий интерфейс. Например, если Hello, Computer и Radio все реализованы IFoo, тогда он может вернуть IFoo.

Ответ 2

Вот как вы можете сделать это с помощью дженериков:

public T GetAnything<T>()
{
   T t = //Code to create instance

   return t;
}

Но вы должны знать, какой тип вы хотели бы вернуть во время разработки. И это означало бы, что вы могли бы просто вызвать другой метод для каждого создания...

Ответ 3

Если вы можете сделать абстрактный класс для всех возможностей, то это настоятельно рекомендуется:

public Hardware GetAnything()
{
     Computer computer = new Computer();

     return computer;    
}

abstract Hardware {

}

class Computer : Hardware {

}

Или интерфейс:

interface IHardware {

}

class Computer : IHardware {

}

Если это может быть что угодно, вы можете использовать "объект" в качестве возвращаемого типа, потому что каждый класс происходит от объекта.

public object GetAnything()
{
     Hello hello = new Hello();

     return hello;    
}

Ответ 4

Ответ Marc должен быть правильным, но в .NET 4 вы также не можете использовать динамический тип.

Это должно использоваться только в том случае, если у вас нет контроля над возвращаемыми вами классами, и нет общих предков (обычно с interop), и только если не использовать динамику, это намного более болезненно, чем использование (литье каждого объекта в каждый шаг:)).

Несколько сообщений в блоге, пытающихся объяснить, когда использовать динамику: http://blogs.msdn.com/b/csharpfaq/archive/tags/dynamic/

public dynamic GetSomething()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio(); 
     return // anyobject

}

Ответ 5

используйте динамическое ключевое слово в качестве возвращаемого типа.

 private dynamic getValuesD<T>()
    {
        if (typeof(T) == typeof(int))
        {
            return 0;
        }
        else if (typeof(T) == typeof(string))
        {
            return "";
        }
        else if (typeof(T) == typeof(double))
        {
            return 0;
        }
        else
        {
            return false;
        }
    }

        int res = getValuesD<int>();
        string res1 = getValuesD<string>();
        double res2 = getValuesD<double>();
        bool res3 = getValuesD<bool>();

//динамическое ключевое слово предпочтительнее использовать в этом случае вместо типа объекта

//потому что динамическое ключевое слово сохраняет базовую структуру и тип данных, чтобы//вы могли напрямую проверить и просмотреть значение.

//в типе объекта вы должны привести объект к определенному типу данных, чтобы просмотреть//базовое значение.

С уважением,

Abhijit

Ответ 6

Чтобы использовать ответ @RQDQ с помощью дженериков, вы можете комбинировать его с Func<TResult> (или некоторыми вариантами) и делегировать ответственность вызывающему:

public T GetAnything<T>(Func<T> createInstanceOfT)
{
    //do whatever

    return createInstanceOfT();
}

Затем вы можете сделать что-то вроде:

Computer comp = GetAnything(() => new Computer());
Radio rad = GetAnything(() => new Radio());

Ответ 7

Тип возврата может быть суперклассом трех классов (либо определенных вами, либо просто использующих object). Затем вы можете вернуть любой из этих объектов, но при получении результата вам нужно вернуть его к правильному типу. Как:

public object GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return radio; or return computer; or return hello //should be possible?!      
}

Тогда:

Hello hello = (Hello)getAnything(); 

Ответ 8

Вы можете просто вернуть объект, поскольку все типы происходят от Object.

public Object GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return radio; or return computer; or return hello //should be possible?!      
}

Затем вы можете применить к соответствующему типу:

Hello hello = (Hello)GetAnything();

Если вы не знали, каким будет тип, вы можете использовать ключевое слово is.

Object obj = GetAnything();
if (obj is Hello) {
    // Do something
}

Говоря это, я бы не хотел писать такой код. Было бы намного лучше иметь интерфейс, который реализуется каждым из ваших классов.

public ISpeak GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return radio; or return computer; or return hello //should be possible?!      
}

interface ISpeak 
{
   void Speak();
}

и каждый из ваших классов реализует интерфейс:

public class Hello : ISpeak
{
    void Speak() {
        Console.WriteLine("Hello");
    }
}

Затем вы можете сделать что-то вроде:

GetAnything().Speak();

Ответ 9

У вас есть несколько вариантов в зависимости от того, почему вы хотите возвращать разные типы.

a) Вы можете просто вернуть объект, и вызывающий может передать его (возможно, после проверки типа) на то, что они хотят. Это означает, конечно, что вы теряете много преимуществ статической типизации.

b) Если все возвращаемые типы имеют общее требование, вы можете использовать generics with constriants.

c) Создайте общий интерфейс между всеми возможными типами возврата и затем верните интерфейс.

d) Переключитесь на F # и используйте соответствие шаблонов и дискриминированные союзы. (Извините, немного держитесь!)

Ответ 10

Пусть метод возвращает объект из общего базового класса или интерфейса.

public class TV:IMediaPlayer
{
   void Play(){};
}

public class Radio:IMediaPlayer
{
   void Play(){};
}

public interface IMediaPlayer
{
   void Play():
}

public class Test
{
  public void Main()
  {
     IMediaPlayer player = GetMediaPlayer();
     player.Play();
  }


  private IMediaPlayer GetMediaPlayer()
  {
     if(...)
        return new TV();
     else
        return new Radio();
  }
}

Ответ 11

Решение Рика - "лучший" способ в большинстве случаев. Иногда, когда это невозможно, вы хотите использовать объект в качестве базового типа. И вы можете использовать этот метод следующим образом:

public object GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return hello; // or computer or radio   
}

Чтобы использовать его, вам нужно использовать оператор as, например:

public void TestMethod()
{
    object anything = GetAnything();
    var hello = anything as Hello;
    var computer = anything as Computer;
    var radio = anything as Radio;

    if (hello != null)
    {
        // GetAnything() returned a hello
    }
    else if (computer != null)
    {
        // GetAnything() returned a computer
    }
    else if (radio != null)
    {
        // GetAnything() returned a radio
    }
    else
    {
        // GetAnything() returned... well anything :D
    }
}

В вашем случае вы хотите вызвать метод воспроизведения. Поэтому это выглядит более подходящим:

interface IPlayable
{
    void Play();
}

class Radio : IPlayable
{
    public void Play() { /* Play radio */ }
}

class Hello : IPlayable
{
    public void Play() { /* Say hello */ }
}

class Computer : IPlayable
{
    public void Play() { /* beep beep */ }
}

public IPlayable GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return hello; // or computer or radio   
}

Ответ 12

Вы можете использовать внешний класс, задавать типы свойств по своему усмотрению, а затем использовать его в своей функции.

public class MultipleOpjects
{
    private List<string> _ObjectOne;
    public List<string> ObjectOne {
        get { return _ObjectOne; }
        set { _ObjectOne = value; }
    }
    private List<object> _ObjectTwo;
    public List<object> ObjectTwo {
        get { return _ObjectTwo; }
        set { _ObjectTwo = value; }
    }
    private object _ObjectThree;
    public object ObjectThree {
        get { return _ObjectThree; }
        set { _ObjectThree = value; }
    }
}
public MultipleOpjects GetAnything()
{
    MultipleOpjects Vrble = new MultipleOpjects();
    Vrble.ObjectOne  = SomeThing1;
    Vrble.ObjectTwo = SomeThing2;
    Vrble.ObjectThree = SomeThing3;

    return Vrble;      
}

Ответ 13

У меня есть идея вернуть несколько типов........

public object GetAnything(object o)
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();
     if(o == Hello){return hello;}
     if(o == Computer {return computer;}
     if(o == Radio) {return radio;}
}

Ответ 14

Определение одного типа для всех не всегда возможно. Даже если это возможно, реализация редко бывает легкой. Я предпочитаю использовать параметры out. Единственное предостережение в том, что вам нужно знать все типы возврата в расширенном режиме:

public void GetAnything(out Hello h, out Computer c, out Radio r)
{
     /// I suggest to:
     h = null;
     c = null;
     r = null; 
     // first, 

     // Then do whatever you have to do:
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();
}

Тип возврата может быть void или что-то еще, например bool a int или предопределенный enum, который может помочь вам проверять исключения или различные случаи, когда этот метод используется.

Ответ 15

Может быть, вам нужен "динамический" тип?

public dynamic GetAnything()
{
     Hello hello = new Hello();
     Computer computer = new Computer();
     Radio radio = new Radio();

     return /*what boject you needed*/ ;`enter code here`   
}