Generics explicit conversion

I implemented an explicit conversion from string to object called Foo.

So => Foo f = (Foo)"foo data"; works

I need to implement a function that cast a string to the generic T, T in this case is Foo datatype.

public T Get<T>(object o){
      // this always return false
      if (typeof(T).IsAssignableFrom(typeof(String)))
      {
            // when i by pass the if above this throws invalid cast exception
            return (T)(object)str;
      }
      return null; 
}

// When I call this, it generated an error
// Invalid cast from 'System.String' to Foo
Foo myObj = Get<Foo>("another foo object"); 

// when I use the dynamic keyword it works but this is C# 4.0+ feature, my function is in the older framework
return (T)(dynamic)str;

Answers


An example that uses Reflection:

class Program
{
    static void Main(string[] args)
    {           
        Foo myObj = TypeResolver.Get<Foo>("Foo data");            
    }
}

class TypeResolver
{
    public static T Get<T>(object obj)
    {
        if (typeof(T).CanExplicitlyCastFrom<string>())
        {                             
            return obj.CastTo<T>();
        }
        return default(T);
    }
}

public static class Extensions
{
    public static bool CanExplicitlyCastFrom<T>(this Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        var paramType = typeof(T);
        var castOperator = type.GetMethod("op_Explicit", 
                                        new[] { paramType });
        if (castOperator == null)
            return false;

        var parametres = castOperator.GetParameters();
        var paramtype = parametres[0];
        if (paramtype.ParameterType == typeof(T))
            return true;
        else
            return false;
    }

    public static T CastTo<T>(this object obj)
    {            
        var castOperator = typeof(T).GetMethod("op_Explicit", 
                                        new[] { typeof(string) });
        if (castOperator == null)
            throw new InvalidCastException("Can't cast to " + typeof(T).Name);
        return (T)castOperator.Invoke(null, new[] { obj });
    }
}

Also take a look at this answer from @Jon Skeet - and specifically the quote about IsAssignableFrom.

I don't think that's possible in a way that you envisioned it.

I'd suggest you put an 'interface contract' on your Foo classes - and then let generics do their work.

e.g. something like this - but this is just a fast solution I typed in...

class Factory 
{
    public static T Create<T, TVal>(TVal obj) where T : class, IFoo<TVal>, new()
    {
        return new T { Value = obj }; // return default(T);
    }
}
interface IFoo<TVal>
{
    TVal Value { get; set; }
}
class Foo : IFoo<string>
{
    public string Value { get; set; }
    public Foo() { }
}
// ...
public T Get<T, TVal>(TVal obj) where T : class, IFoo<TVal>, new()
{
    return Factory.Create<T, TVal>(obj);
}

And you can call it in a similar way - providing that you have that luxury - know the types etc. (but you can work this out and adjust if needed)

Foo foo = Get<Foo, string>("another text");

If you go via (object) then it just does a type-check cast or a box/unbox (in IL terms: an unbox-any) - it will not use operators. The only way to use generics and operators together is via (dynamic) instead of (object), but this does a little work at runtime.


Need Your Help

Android - call a method when a key is pressed in the onscreen keyboard in android

java android android-softkeyboard

I want to execute a java method whenever the user presses a key on the onscreen keyboard, in android. For instance, the user opens up the keyboard and presses "T" (or any other key), the function i...

Android Getting value from an Integer arraylist becomes a number

java android

I am new to Android and from what I read here most of the question goes to Imageview setting image. Here is my problem same as ImageView errors