Deane
Deane

Reputation: 8773

Using generic methods, is it possible to get different types back from the same method?

Could I have something like this:

int x = MyMethod<int>();
string y = MyMethod<string>();

So, one method returning different types based on T. Of course, there would be logic inside the method to ensure it was returning the correct thing.

I can never get something like this to run. It complains that it can't cast the return value to T:

public static T MyMethod<T>()
{
  if(typeof(T) == typeof(Int32))
  {
    return 0;
  }
  else
  {
    return "nothing";
  }
}

Upvotes: 5

Views: 523

Answers (5)

dkackman
dkackman

Reputation: 15579

@Nick is correct in his comment that your code won't compile. But assuming you mean:

public static T MyMethod<T>()
{
  if(typeof(T) == typeof(Int32))
  {
    return 0;
  }
  else
  {
    return "nothing";
  }
}

It is can be tricky to make generics non generic like you are attempting (and really contravenes the whole point), but this should work:

public static T MyMethod<T>()
{
  if(typeof(T) == typeof(Int32))
  {
    return (T)(object)0;
  }
  else if(typeof(T) == typeof(string))
  {
    return (T)(object)"nothing";
  }

   return default(T);
}

Upvotes: 0

Sean
Sean

Reputation: 62542

Slightly off topic, but if you're trying to do this thing then it may be that your design is wrong...

Why not overload the method and set the result as an out paramter:

void MyMethod(out int result)
{
  result=0;
}

void MyMethod(out string result)
{
  result="my value";
}

Then you can say:

int value;
MyMethod(out value);

And the compiler will select the right version

Upvotes: 1

3Dave
3Dave

Reputation: 29071

This isn't valid as there is no guarantee that T is castable/convertable to string or int.

Generics are NOT variants - ie, types that can hold anything - they are compile-time resolved to a real type. Your code doesn't compile because it shouldn't. You can get around the compile-time issues using some of the hacks posted here, but this is really a logic problem. Step back and rethink what you're trying to do instead of trying to get around the compiler.

Upvotes: 0

Mikael Svenson
Mikael Svenson

Reputation: 39695

You could do, if you want a "null" type value returned if it's not an int. But if you want a string in all other cases, check the other answers.

public static T MyMethod<T>()
{
  if(typeof(T) == typeof(Int32))
  {
    return (T)(object)0;
  }
  else
  {
   return default(T); // or null
  }
}

Upvotes: 0

JaredPar
JaredPar

Reputation: 755557

Try the following

public static T MyMethod<T>() {
  if ( typeof(T) == typeof(Int32) ) {
    return (T)(object)0;
  } else {
    return (T)(object)"nothing";
  }
}

The trick here is the casting to object. What you are trying to do is inherently unsafe since the compiler cannot infer that 0 or "nothing" are convertible to any given T. It is unbounded after all. So just tell the compiler explicitly it's not safe with casting to object.

Upvotes: 10

Related Questions