22

This is what I need to do:

object foo = GetFoo();
Type t = typeof(BarType);
(foo as t).FunctionThatExistsInBarType();

Can something like this be done?

Marek Grzenkowicz
  • 17,024
  • 9
  • 81
  • 111
  • How do you know that it is a string you want on the left side of the equals in the last line of your example? In other words what are you going to do with bar that means you can not use "object bar = (object)foo;" ? – Martin Brown Jan 21 '09 at 12:29
  • I don't, string was only an example. I edited the snippet. – Marek Grzenkowicz Jan 21 '09 at 12:58

5 Answers5

20

You can use the Convert.ChangeType method.

object foo = GetFoo(); 
Type t = typeof(string);
string bar = (string)Convert.ChangeType(foo, t);
GvS
  • 52,015
  • 16
  • 101
  • 139
  • 11
    This is useful only if the object implements IConvertible – Quassnoi Jan 21 '09 at 11:03
  • 5
    I used string only as an example. The problem is I don't know the target type so I cannot perform this xyz bar = (xyz)Convert.Change... cast. – Marek Grzenkowicz Jan 21 '09 at 11:33
  • Convert.ChangeType is not casting, it's converting. i.e. creating a new object of the type specified. If you want to cast to say ICollection this won't work. – Hoots Jul 29 '14 at 12:08
  • ? in your example here I guess `var bar = (string) foo;` would just do the same thing ... you didn't cast using `Convert.ChangeType` but you casted the moment you used `(string)...` – derHugo Jul 12 '18 at 14:56
14

No, you cannot. C# does not implement duck typing.

You must implement an interface and cast to it.

(However there are attempts to do it. Look at Duck Typing Project for an example.)

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Quassnoi
  • 413,100
  • 91
  • 616
  • 614
6

Since dynamics were added to c#, I think we can do it in this way:

class Program {
    static void Main(string[] args) {
        List<int> c = new List<int>(); 
        double i = 10.0;
        Type intType = typeof(int);
        c.Add(CastHelper.Cast(i, intType)); // works, no exception!
    }
}

class CastHelper {
    public static dynamic Cast(object src, Type t) {
        var castMethod = typeof(CastHelper).GetMethod("CastGeneric").MakeGenericMethod(t);
        return castMethod.Invoke(null, new[] { src });
    }
    public static T CastGeneric<T>(object src) {
        return (T)Convert.ChangeType(src, typeof(T));
    }
}
rmrfhome
  • 136
  • 1
  • 8
4

Your original question was flawed in that you ask to treat a variable as a type which is not known at compile time but note that you have string defined on the left hand side when you declare your variable. C# as of 3.5 is statically typed.

Once dynamic is available you could do something like this:

dynamic foo = GetFoo();
foo.FunctionThatExistsInBarType(); 

For when you don't know what the type is but you know it will always support the instance method FunctionThatExistsInBarType();

for now you are forced to use reflection (or code gen which really amounts to much the same thing but more expensive up front and faster later).

// any of these can be determined at runtime
Type t = typeof(Bar);
string methodToCall = "FunctionThatExistsInBarType";
Type[] argumentTypes = new Type[0];
object[] arguments = new object[0];
object foo;
// invoke the method - 
// example ignores overloading and exception handling for brevity
// assumption: return type is void or you don't care about it
t.GetMethod(methodToCall, BindingFalgs.Public | BindingFlags.Instance)
    .Invoke(foo, arguments);
ShuggyCoUk
  • 36,004
  • 6
  • 77
  • 101
-1

Provided you know all required types at compile-time, duck typingis (sort of) possible:

class BarFoo {}
class Foo {}
class Bar {}

class Program
{
    static void Main( )
    {
        var foo = new Foo( );
        var bar = new Bar( );
        var barfoo = new BarFoo( );

        Console.WriteLine(DoStuff(foo));
        Console.WriteLine(DoStuff(bar));
        Console.WriteLine(DoStuff(barfoo));

    }

    static string DoStuff(Foo foo) { return "DoStuff(Foo foo)"; }
    static string DoStuff(Bar bar) { return "DoStuff(Bar bar)"; }
    static string DoStuff(Base fb) { return "DoStuff(object fb)"; }
}

Output:

Dostuff(Foo foo)
Dostuff(Bar bar);
DoStuff(object fb);

If you end up implementing a lot of methods that basically do exactly the same, consider implementing an interface.

Marcus Hansson
  • 816
  • 2
  • 8
  • 17