George Vovos
George Vovos

Reputation: 7618

Cast instance of generic type to "template" instance

This might be a silly question and I don't really need this for anything but I was just curious...

The best way to describe it is using a example so here it is:

using System;

namespace GenericExample
{
    public interface IFoo { }

    public interface IFoo2 { }

    public class Foo1: IFoo , IFoo2 { }

    public class Foo2 : IFoo, IFoo2 { }

    public class MyGeneric<T> where T : IFoo , IFoo2, new() { }

    internal class Program
    {
        public static void Main(string[] args)
        {
            MyGeneric<Foo1> obj1 = new MyGeneric<Foo1>();
            MyMethod(obj1);//I can treat obj1 as MyGeneric<T> in MyMethod

            MyGeneric<Foo2> obj2 = new MyGeneric<Foo2>();

           //But can I use is as MyGeneric<T> in this method???
           //MyGeneric<?> obj3 = null;
           //obj3 = (MyGeneric<?>)obj1; 
           //obj3 = (MyGeneric<?>)obj2; 
            Console.ReadLine();
        }

        public static void MyMethod<T>(MyGeneric<T> arg) where T : IFoo, IFoo2, new() 
        {

        }
    }
}

I don't think it is possible to treat obj1 as MyGeneric< T> in Main
but at the same time it feels strange since I can pass it as a MyGeneric< T> argument

Upvotes: 0

Views: 71

Answers (2)

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37000

There is no common base-type for MyGeneric and MyGeneric, so I assume the answer is no. In contrast to Java generics in C# are strongly typed types and not just placeholders, so they don´t have anything in common - except a name. However actually they are different types, think of them as just MyGeneric<T1> being a type Foo and MyGeneric<T2> being Bar.

A way around this is to define a non-generic version of your generic class:

public class Foo1 { }
public class MyNonGeneric { }
public class MyGeneric<T> : MyNonGeneric where T : new() { }

Upvotes: 1

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43876

You cannot cast it to MyGeneric<T> in Main because in the scope of Main there is no such type as T. Actually it's not really clear what you mean by

to treat obj1 as MyGeneric< T> in Main

When passing obj1 to MyMethod you don't "treat it as MyGeneric<T>". It is the compiler which infers the type of T for you. It knows that T is Foo1 here and translates your call

MyMethod(obj1);

to

MyMethod<Foo1>(obj1);

So the type of the parameter arg inside of MyMethod will at runtime also be MyObject<Foo1>, not an unspecified MyObject<T>.

Upvotes: 1

Related Questions