简体   繁体   中英

Calling methods and properties of reference types in generic classes

While there are plenty of example on generics using primitve types like int ans string I couldn't really find one using proper classes. Here is the scenario

    //main program
    class Program
    {
        static void Main(string[] args)
        {
            MyClass<TClass> mt = new MyClass<TClass>();

            mt.GetValueFromType();

            Console.ReadKey();
        }
    }

This is the generic class

public class MyClass<T>  
{
    public void GetValueFromType()
    {
        Console.WriteLine("Genric method called");

         //Need to call the method MyTypeMethod() from the reference type sent in here.                
         //How?


    }
}

One of the types that will be sent in to the generic class as

public class TClass
{

    public void MyTypeMethod()
    {
        Console.WriteLine("Type method called");
    }
}

Can this even be done in C# or do I need to refer to an interface of TClass with the new MyClass<T>().GetValueFromType() method ?

If I have to use interface then why use generics at all?

All the compiler can infer is that generic parameter T is of type Object so only the methods and properties for System.Object will be available. In order to get beyond that, you need to tell the compiler that T is expected to be derived from a base type, or implements specific interfaces. This is called a generic constraint:

public abstract class BaseClass
{

  public virtual void MyTypeMethod()
  {     
  }

}


 public class TClass : BaseClass
 {

    public override void MyTypeMethod()
    {
       Console.WriteLine("Type method called");
    }

 }



public class MyClass<T> where T: BaseClass
{
    public void GetValueFromType(T value)
    {
        Console.WriteLine("Genric method called");
        value.MyTypeMethod();
    }
}

So in this example any class derived from BaseClass can be used for the generic parameter T. You can also do the same thing with an interface. But in that case it would be more along the lines of that T implements the constrained interface. Usually the interface route is much more flexible since c# does not allow multiple inheritance.

You can use generic constrains what I think will accomplish what your after:

public class MyClass<T> where T: TClass
{
    public void GetValueFromType(T value)
    {
        Console.WriteLine("Genric method called");
        value.MyTypeMethod();
    }
}

I'd create an abstract base class, say MyBase that defines the method MyTypeMethod() :

public abstract class MyBase
{
    public virtual void MyTypeMethod() { }
}

All the classes you want to use in the generic class would inherit from this. Override and implement MyTypeMethod()

Modify your generic class:

public class MyClass<T> where T : MyBase
{
    public void GetValueFromType()
    {
        T.MyTypeMethod();        
        Console.WriteLine("Generic method called");

    }
}

You could also use an interface as gleng suggested.

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