Disappointed
Disappointed

Reputation: 1120

Do we really need generic class with type constraint?

Sorry if title of question is a little bit vague.
Suppose we have the following code

class ReportManager<T> where T : IPrint
{
    public void MakePaperCopy(T t)
    {
        //...
        t.Print();
        //...
    }
}

public interface IPrint
{
    void Print();
}

It can be easily remade to non-generic version. Like this

class ReportManager
{
    public void MakePaperCopy(IPrint print)
    {
        //...
        print.Print();
        //...
    }
}

Are there some advantages in first case ? it seems no.
Can i say that every generic class with single where T: ISomeInterface can be easily remade to non-generic version and it should be done because it reduces the complexity of code ?

Upvotes: 1

Views: 84

Answers (4)

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

In the first place, generics avoid a lot of casts. This can ends up in significant performance gains in intensive applications and services.

Secondly, it's not the same defining that a generic type parameter accepts any implementation of IPrint (non-generic) than that the whole type will handle objects which are forced to implement IPrint (generic).

Try to work on the following type requirement without generics:

  • I want that T to be IPrint and inherit PrintablePaper.

Without generics, sadly, this would be implemented using reflection:

// Ugly as hell. And error prone, because it's verified during
// run-time...
if(typeof(IPrint).IsAssignableFrom(typeof(T)) && typeof(T).IsSubclassOf(typeof(PrintablePaper)) 
{
}

With generics: T : PrintablePaper, IPrint and try to give a wrong type as generic argument, and compiler will say: slap in your face, slap in your face, ....

Basically, in terms of high-level programming, generics were introduced to enforce strongly-typing in C# even more. Generic constraints provide details to what would be an acceptable generic argument during compile-time. That is, generics are a good way to close a software architecture/design to grow based on specs defined by generic constraints.

About the whole repository sample, if your report manager will never need to handle specializations of IPrint, generics are useless in that particular case: accepting implementations of IPrint or a type which mandatorily will implement IPrint is almost the same in your case.

In your case, it would be useful if you would need to inherit that class:

class ReportManager<T> where T : IPrint
{
    public void MakePaperCopy(T t)
    {
        //...
        t.Print();
        //...
    }
}

class SpecializedReportManager : ReportManager<FancyReport>
{
    // Beat this without generics!!
    // In inherited classes, you can work with the IReport
    // implementation directly and without casts!
    public void MakePaperCopy(FancyReport t)
    {
        //...
        t.Print();
        //...
    }
}

Upvotes: 4

romain-aga
romain-aga

Reputation: 1561

It's not useless in all cases.
If you want to return this T, then you may want to know the exact type.
Because when you are returning it, you can access to all the (accessible) members from the derived class, not only those from the base class/interface.

Upvotes: 5

decPL
decPL

Reputation: 5402

After commenting on romain-aga's post - there's yet another reason, on top of what everyone else said. If you have a constraint referencing a generic interface (say where T : IComparable<T>) you simply won't be able to remake it into a non-generic version.

Upvotes: 0

Dennis_E
Dennis_E

Reputation: 8904

The generic form will prevent boxing in case of value types.

Also, you can have T implement multiple interfaces:

class ReportManager<T> where T : IPrint, IConvertible, IAnotherInterface

The 2nd form will obviously not work in that case.

Upvotes: 2

Related Questions