简体   繁体   中英

Retrieve generic object type when casted to base class

I have the following situation :

 public interface IBaseType
 {
      public void InterfaceMethod ()
 }

 public class MyType<T> : IBaseType
 {
    public void InterfaceMethod () {};
    public string DoSomething () 
    {  
       if ( typeof(T) == typeof(string) ) return "String";
       if ( typeof(T) == typeof(int) ) return "Int";
       ... so on
    }
 }

 List<IBaseType> list = new List<IBaseType> ();

 list.Add ( new MyType<int> () );
 list.Add ( new MyType<long> () );
 list.Add ( new MyType<string> () );

Now how can i retreive the correct generic when accessing to list elements ?

Example :

 IBaseType element = list[1] ;
 //here i would cast back element to MyType<long> type beacuse i would use method DoSomething()

Thanks in advance for help and sorry for my poor English.

An easy way to handle this is to add a Type property into IBaseType

public interface IBaseType
{
    void InterfaceMethod ();
    Type GenericType { get; }
}

Then, in your overridden class:

public class MyType<T> : IBaseType
{
    public Type GenericType { get { return typeof(T); }
}

You can also look up the Type of a generic class at run-time using Type.GetGenericArguments , but that will involve the performance penalty of using reflection.

I agree with commenter Lasse V. Karlsen: there is something fundamentally wrong with the design if you are doing explicit type-checking and conditionally executing code in a generic class (or any class, for that matter.

Without more context, it's hard to know for sure what you should be doing here. But it seems that you have a list of IBaseType instances, only some of which are types that implement DoSomething() (otherwise, that method would be in the interface, right?).

In that case, I think what you should do is introduce an intermediate type, from which all your explicitly-typed (ie non-generic ) classes can inherit:

interface IBaseType { void InterfaceMethod(); }

abstract class MyType : IBaseType
{
    public void InterfaceMethod() { ...implementation here... }

    public abstract string DoSomething();
}

Then you'd have separate subclasses, one for each subtype:

class MyTypeInt32 : MyType
{
    public override string DoSomething() { return "Int32"; }
}

class MyTypeString : MyType
{
    public override string DoSomething() { return "String"; }
}

// etc.

Then you can do this:

IBaseType element = list[1];

MyType myTypeElement = element as MyType;

if (myTypeElement != null)
{
    string result = myTypeElement.DoSomething();
}

That would be the proper use of polymorphism. Note the almost-complete lack of special-case, type-specific code. The above just uses the type system itself to organize the type-specific logic.

Finally, I'll note that if it happens that the InterfaceMethod() is also a different implementation per-type, then you should just make an IMyType interface instead of the abstract class, since each type-specific class is where the actual interface implementation should go.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM