C# Return different types?

C#Types

C# Problem Overview


I have a method which returns different types of instances (classes):

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?!      
}

How can I do this and later work with the variables, e.g. radio.Play(), etc?

Do I need to use generics, and if so, how?

C# Solutions


Solution 1 - C#

Here is how you might do it with generics:

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

   return t;
}

But you would have to know what type you wanted returned at design time. And that would mean that you could just call a different method for each creation...

Solution 2 - C#

If there is no common base-type or interface, then public object GetAnything() {...} - but it would usually be preferable to have some kind of abstraction such as a common interface. For example if Hello, Computer and Radio all implemented IFoo, then it could return an IFoo.

Solution 3 - C#

use the dynamic keyword as return type.

 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>();

The dynamic keyword is preferable to use in this case instead of an object type because dynamic keyword keeps the underlying structure and data type so that you can directly inspect and view the value.

In object type, you have to cast the object to a specific data type to view the underlying value.

regards,

Abhijit

Solution 4 - C#

Marc's answer should be the correct one, but in .NET 4 you couldn't also go with dynamic type.

This should be used only if you have no control over the classes you return and there are no common ancestors ( usually with interop ) and only if not using dynamic is a lot more painful then using(casting every object in every step :) ).

Few blog post trying to explain when to use dynamic: 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

}

Solution 5 - C#

If you can make a abstract class for all the possibilities then that is highly recommended:

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

     return computer;    
}

abstract Hardware {

}

class Computer : Hardware {

}

Or an interface:

interface IHardware {

}

class Computer : IHardware {

}

If it can be anything then you could consider using "object" as your return type, because every class derives from object.

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

     return hello;    
}

Solution 6 - C#

To build on the answer by @RQDQ using generics, you can combine this with Func<TResult> (or some variation) and delegate responsibility to the caller:

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

    return createInstanceOfT();
}

Then you can do something like:

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

Solution 7 - C#

You can have the return type to be a superclass of the three classes (either defined by you or just use object). Then you can return any one of those objects, but you will need to cast it back to the correct type when getting the result. Like:

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?!      
}

Then:

Hello hello = (Hello)getAnything(); 

Solution 8 - C#

You could just return an Object as all types are descended from 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?!      
}

You could then cast to its relevant type:

Hello hello = (Hello)GetAnything();

If you didn't know what the type was going to be then you could use the is keyword.

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

This being said I would be reluctant to write code like that. It would be much better to have an interface which is implemented by each of your classes.

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();
}

and have each of your classes implement the interface:

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

You could then do something like:

GetAnything().Speak();

Solution 9 - C#

You have a few options depending on why you want to return different types.

a) You can just return an object, and the caller can cast it (possibly after type checks) to what they want. This means of course, that you lose a lot of the advantages of static typing.

b) If the types returned all have a 'requirement' in common, you might be able to use [generics with constriants][1].

c) Create a common interface between all of the possible return types and then return the interface.

d) Switch to F# and use [pattern matching][2] and discriminated unions. (Sorry, slightly tongue in check there!)

[1]: http://msdn.microsoft.com/en-us/library/d5x73970.aspx "generics with constraints" [2]: http://msdn.microsoft.com/en-us/library/dd547125.aspx

Solution 10 - C#

Let the method return a object from a common baseclass or interface.

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();
  }
}

Solution 11 - C#

Rick's solution is the 'best' way to go in most cases. Sometimes when that's not available you want to use object as base type. And you could use the method like this:

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

     return hello; // or computer or radio   
}

To use it, you will want to use the as operator, like this:

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
    }
}

In your case you want to call a method play. So this'd seem more appropriate:

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   
}

Solution 12 - C#

You could use external class, set the properties types as you wish, then use it in your function.

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;      
}

Solution 13 - C#

Defining a single type for all is not always possible. Even if when you can, the implementation is rarely easy. I prefer to use out parameters. The only caveat is that you need to know all the return types in advanced:

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();
}

The return type can be a void, or something else, like bool an int or a predefined enum which can help you check for exceptions or different cases wherever the method is used.

Solution 14 - C#

It's a sample using Generic Types.

public T GetAnything<T>() where T : class, new()
    => new T();

And you'll use this method calling this way:

var hello = GetAnything<Hello>();

In this case, you can use an interface to specify a type to pass as parameter.

public T GetAnything<T>() where T : ISomeInterface, new()
    => new T();

You must have a parameterless construtor in each class to use new() constraint.

Follow the full sample:

internal sealed class Program
{
    private static void Main(string[] args)
    {
        GetAnything<Hello>().Play();
        GetAnything<Radio>().Play();
        GetAnything<Computer>().Play();
    }

    private static T GetAnything<T>() where T : ISomeInterface, new()
        => new T();
}

internal interface ISomeInterface
{
    void Play();
}

internal sealed class Hello : ISomeInterface
{
    // parameterless constructor.
    public Hello() { }
    public void Play() => Console.WriteLine("Saying hello!");
}

internal sealed class Radio : ISomeInterface
{
    // parameterless constructor.
    public Radio() { }
    public void Play() => Console.WriteLine("Playing radio!");
}

internal sealed class Computer : ISomeInterface
{
    // parameterless constructor.
    public Computer() { }
    public void Play() => Console.WriteLine("Playing from computer!");
}

Solution 15 - C#

My post here is strictly related to Blazor v5 but should work in 3.x as well. Additionally, I'm using these methods with bootstrap 4.5 and 5.0 beta 1 but you could easily adapt it to use style's instead of classes or use your own classes.

To those recommending dynamic, I thank you. The dynamic type seems like it can be very valuable when used correctly. Most of the time you'll probably use an interface but this wasn't plausible for me. I went ahead and updated my project with a dynamic return type and it's working great while being the quickest, cleanest solution.

I previously added the following extension methods to boolean types to help me avoid long ternary operators in razor page code. Here are the 3 main extension methods I use to accomplish it:

public static T Then<T>(this bool value, T result) => value ? result : default;    
public static T Then<T>(this bool value, T thenResult, T elseResult) => value ? thenResult : elseResult;
public static T Else<T>(this bool value, T result) => !value ? result : default;

The following are examples of that implementation:

<div class="@Hidden.Then("d-none")">
    Hidden content...
</div>

Note: ErrorOrWarning would hide the content if there was no error/warning so I could default it to yellow/italic but this is an example so please use your imagination:

<div class="@ErrorOrWarning.Else("d-none")" style="@Error.Then("color:red;font-weight:bold;","color:yellow;font-style:italic;")">
    Error/Warning content...
</div>

This is the typical implementation without the extension methods. It's common to see this technique in Blazor guides/tutorials/videos online. There are cleaner ways to handle it but this is the basic idea:

<div class="@(ErrorOrWarning ? "" : "d-none")" style="@(Error ? "color:red;font-weight:bold;" : "color:yellow;font-style:italic;")">
    Error/Warning content...
</div>

While this might not seem like too big a difference, if you have a lot of dynamic content/styles driving your page, it can get really messy. With those 3 lines of code you can enhance the readability and cleanliness and it really does reduce risk of typos. Adding two more extension methods, you can reduce the risk even further Note: Again, this is using bootstrap class "d-none" for the style "display:none!important" but you could just as easily replace with your own usage:

public static string ThenShow(this bool value) => value ? "" : "d-none";
public static string ThenHide(this bool value) => value ? "d-none" : "";

The limitation I previously faced was when using the overloaded Then(thenResult, elseResult), each of the parameters must be of the same type. 99% of the time this is fine. Actually, another 0.5% of the time it's still okay because you can probably solve it quickly with a .ToString() or an explicit cast.

What I ran into, and what took me to this post was: I have a control you can imagine as a button. There is an Enum property allowing the user to select an icon to display. The selected Enum dynamically populates a readonly MarkupString property. As an alternative option, they can use the ChildContent (or IconContent in my example) of type RenderFragment. This will let them manually add anything they want (maybe an iFrame to stackoverflow haha) but my intention is for them to add style, most likely in the form of an icon.

I know I can cast/convert one to the other however my existing extension method is so clean and simple, it would be great to be able to use pass the MarkupString and RenderFragment together as parameters, conditionally output to the razor page. So, thanks to this post, I changed my Then(thenResult, elseResult) extension methods to use unique generic parameter types and return a dynamic type like so:

public static dynamic Then<T,E>(this bool value, T thenResult, E elseResult) => value ? thenResult : elseResult;

Now in my razor page I have a very simple line for the icon output. Note: IconContent is a RenderFragment and IconMarkup is a MarkupString.

@((@IconContent == null).Then(IconMarkup, IconContent))

And because I love extension methods and I'm typing this up, I took it a step further with another extension method:

public static bool IsNull(this RenderFragment value) => value == null;

Which enables the extremely clean and simple:

@IconContent.IsNull().Then(IconMarkup, IconContent)

Here's the extra extension method I mentioned above which converts a string to a MarkupString. It might be overkill but I like it.

public static MarkupString ToMarkup(this string value) => (MarkupString)value;

Let me know if you have a better recommendation or if you think I'm doing something wrong. I'm sure this post makes it seem like I overuse extension methods but I really don't. I keep their use limited to outcomes such as I've outlined in this post.

Solution 16 - C#

create an object then put all your data in it. Return that object. Cast the object as an array (Array)yourObject then cast the values of the array as an integer or what you want.

class Program
{
    static void Main(string[] args)
    {   
        object data = MyMethod();
        Array dataarray = (Array)data;
        string astring = (string) dataarray.GetValue(0);
        int aninteger = (int)dataarray.GetValue(1);
        Console.WriteLine(astring);
        Console.WriteLine(aninteger);
    }

    static object MyMethod()
    {   
        /// create an object array

        object[] myarray = new object[2];

        /// put your values in it (remeber their order to cast them right later)

        myarray[0] = "any string";
        myarray[1] = 3;
        
        /// convert the object array to a singel object
        
        object _myarray = (object) myarray;
        return _myarray;
    }

}

This method of retuning multipile values as one object is very helpful for building a program with ParameterizedThreadStart. (I'm sorry for bad my explination but the code works and everyone should be able to understand it)

Solution 17 - C#

As already mentioned in other answers before, it is preferable to have some kind of abstraction as a common interace or abstract base class.

In some cases it is not possible or not appropiate to introduce such abstraction. As alternative some answers suggests returning an object and cast it back to the original type: public object GetAnything() {...}.

The only "problem" with that solution is, that the caller have to know of what possible type the object can be. To avoid that problem we can introduce an object that provides an "interface" that directly communicates the possible object types to the caller.

The following code uses a struct to avoid additional heap allocation. The DynamicObject just contains one object and the needed methods. You may want to add null checks in the DynamicObject constructors.

// Usage of DynamicObject.
public void ExampleUsage()
{
    DynamicObject dynamicObject = GetAnything();
    if (dynamicObject.TryGetRadio(out Radio radio))
        radio.Play();
    else
        ; // ...
}

public DynamicObject GetAnything()
{
    Random rnd = new Random();
    switch (rnd.Next(0, 3))
    {
        case 0:
            return new DynamicObject(new Hello());
        case 1:
            return new DynamicObject(new Computer());
        case 2:
            return new DynamicObject(new Radio());
        default:
            throw new InvalidOperationException(); // Not possible.
    }
}

// Implementation of DynamicObject.
public struct DynamicObject
{
    private readonly object _value;

    public DynamicObject(Hello hello) => _value = hello;

    public DynamicObject(Computer computer) => _value = computer;

    public DynamicObject(Radio radio) => _value = radio;

    public bool TryGetHello(out Hello hello) => TryGetAsConcreteObject(out hello);

    public bool TryGetComputer(out Computer computer) => TryGetAsConcreteObject(out computer);

    public bool TryGetRadio(out Radio radio) => TryGetAsConcreteObject(out radio);

    private bool TryGetAsConcreteObject<T>(out T value)
    {
        if (_value is T concreteObject)
        {
            value = concreteObject;
            return true;
        }
        else
        {
            value = default(T);
            return false;
        }
    }
}

Solution 18 - C#

May be you need "dynamic" type?

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneMiView Question on Stackoverflow
Solution 1 - C#RQDQView Answer on Stackoverflow
Solution 2 - C#Marc GravellView Answer on Stackoverflow
Solution 3 - C#Abhijit OjhaView Answer on Stackoverflow
Solution 4 - C#tbtView Answer on Stackoverflow
Solution 5 - C#Rick KuipersView Answer on Stackoverflow
Solution 6 - C#aw04View Answer on Stackoverflow
Solution 7 - C#TudorView Answer on Stackoverflow
Solution 8 - C#Joe AxonView Answer on Stackoverflow
Solution 9 - C#mavnnView Answer on Stackoverflow
Solution 10 - C#GlennView Answer on Stackoverflow
Solution 11 - C#AidiakapiView Answer on Stackoverflow
Solution 12 - C#Hasan Khaled Al-BzoorView Answer on Stackoverflow
Solution 13 - C#mm_View Answer on Stackoverflow
Solution 14 - C#Arthur AugstenView Answer on Stackoverflow
Solution 15 - C#ZacView Answer on Stackoverflow
Solution 16 - C#serageView Answer on Stackoverflow
Solution 17 - C#Andre KamplingView Answer on Stackoverflow
Solution 18 - C#TadeuszView Answer on Stackoverflow