jwaliszko
jwaliszko

Reputation: 17064

How to perform conversion from object reference

class Mock
{
    public static explicit operator String(Mock s)
    {
        return "ok";
    }
}

static T GetValue<T>(object o)
{
    return (T)o;
}

Mock m = new Mock();
var v1 = (string) m;
var v2 = GetValue<string>(m);   // InvalidCastException is thrown.
                                // How to modify GetValue method
                                // internally, without changing its
                                // signature, for this casting to work ?

Regards

Upvotes: 4

Views: 123

Answers (3)

Paul Sasik
Paul Sasik

Reputation: 81479

How about this: var v2 = GetValue<string>((string)m); ?

This does not modify the GetValue method, rather casts the parameter sent into it. You retain your signature. The cast looks a bit redundant but you have to specify the type for GetValue anyway...

Upvotes: 0

JaredPar
JaredPar

Reputation: 754763

The reason the direct cast succeeds and the GetValue method fails is because the direct cast method is using the explicitcast operator on the Mock<T> type. This explicit cast operator is not available in the generic version because the C# compiler only sees T and hence doesn't bind to the implicit conversion operator but instead chooses to do a CLR conversion.

The easiest way to get this to work is to add an interface to represent this conversion and then constraint T to implement the interface

interface IConvertToString {
  string Convert();
}

public class Mock : IConvertToString {
  public string Convert() {
    return "ok";
  }
}

public static T GetValue<T>(T o) where T : IConvertToString {
  return o.ConvertToString();
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500695

Two options:

  • Use reflection to find the conversion and invoke it
  • Use dynamic typing if you're using C# 4

Using reflection is likely to be painful. The dynamic approach is simpler if you can get away with it:

public static T GetValue<T>(dynamic d)
{
    return (T) d;
}

That isn't a particularly drastic change to the signature, but if you wanted to keep it exactly the same, you could use:

public static T GetValue<T>(object o)
{
    dynamic d = o;
    return (T) d;
}

Upvotes: 2

Related Questions