Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a virtual generic method in C#

I have some base classes like this:

public class AbstractData
{
    public int ID { get; set; }
}

public class Person: AbstractData
{
    public string Name { get; set; }
}

public class AbstractManager<T> where T: AbstractData
{
    public virtual List<T> GetAll()
    {
    }

    public virtual T GetOne(int id)
    {
    }
}

public class PersonManager: AbstractManager<Person>
{
    public override List<Person> GetAll()
    {
        //...
    }

    public override Person GetOne(int id)
    {
        //...
    }
}

Now, I have a Windows Forms base class, like this:

public class BaseForm: Form
{
    public virtual AbstractManager<T> GetManager<T>() where T: AbstractData
    {
        return null;
    }
}

and a derived form:

public class PersonForm: BaseForm
{
    public override AbstractManager<T> GetManager<T>()
    {
        return new PersonManager();
    }
}

The problem is, I keep getting compile errors on the PersonForm class:

Cannot implicitly convert type 'PersonManager' to 'AbstractManager<T>'

Is there a way in which I can create this virtual method and have every class derived from BaseForm return the concrete representation of the AbstractManager?

If I get rid of the generic on the AbstractManager class then I compile OK (with a few code changes), but then the GetAll method can't return a List<T>. It would have to return a List<AbstractData> instead, which causes issues in converting from List<Person> to List<AbstractData>.

Any help would be appreciated.

like image 410
user3215491 Avatar asked Jan 20 '14 14:01

user3215491


People also ask

How do you create a generic method?

Generic MethodsAll generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method's return type ( < E > in the next example). Each type parameter section contains one or more type parameters separated by commas.

How do you create a generic method in C#?

You can create an instance of generic classes by specifying an actual type in angle brackets. The following creates an instance of the generic class DataStore . DataStore<string> store = new DataStore<string>(); Above, we specified the string type in the angle brackets while creating an instance.

How do you declare a generic interface?

You can declare variant generic interfaces by using the in and out keywords for generic type parameters. ref , in , and out parameters in C# cannot be variant. Value types also do not support variance. You can declare a generic type parameter covariant by using the out keyword.

How do you declare a generic type in a class explain?

The declaration of a generic class is almost the same as that of a non-generic class except the class name is followed by a type parameter section. The type parameter section of a generic class can have one or more type parameters separated by commas.


1 Answers

First off all, please never do this:

class C<T>
{
    void M<T>(T t) { }
}

Now we have two things named T both in scope and they are different. This is legal but extremely confusing. Choose better names for your type parameters.

Let's simplify your example:

class FruitBasket<T> where T : Fruit { }
class AppleBasket : FruitBasket<Apple> { }
class C
{
    public static FruitBasket<T> GetBasket<T>() where T: Fruit 
    {
        return new AppleBasket();
    }
}

Now do you see why this is wrong? What if someone calls C.GetBasket<Orange>() and you hand them a basket of apples?

Any help would be appreciated.

What's step one of getting out of a hole? STOP DIGGING.

You have Genericity Happiness Disease, which is common to C# programmers who are discovering the power of the generic type system and then want to use it for everything whether that makes sense or not. Stop trying to capture all the relationships in your business process in the generic type system; that's not what it was designed for.

The test is: can you say "an apple basket is a basket of apples, where apples are a kind of fruit" and have someone who is not a programmer agree with you? Yes. Can you say "a person manager is an abstract manager of persons where person is a kind of abstract data" and have someone who is not a programmer agree with you? No. Then you are not successfully modeling the business domain in the type system. Start over, avoid generics, and try to come up with relationships between types that make sense.

like image 101
Eric Lippert Avatar answered Nov 10 '22 15:11

Eric Lippert