MalcomTucker
MalcomTucker

Reputation: 7477

C# generics - what is gained by making a wrapper class generic?

Consider this generic class:

public class Request<TOperation> 
    where TOperation : IOperation
{
    private TOperation _operation { get; set; }

    public string Method { get { return _operation.Method; } }

    public Request(TOperation operation)
    {
        _operation = operation;
    }
}

What real benefits does the generic version above offer over this non-generic version below?

public class Request
{
    private IOperation _operation { get; set; }

    public string Method { get { return _operation.Method; } }

    public Request(IOperation operation)
    {
        _operation = operation;
    }
}

The IOperation interface is:

public interface IOperation
{
    string Method { get; }
}

Upvotes: 12

Views: 1591

Answers (4)

Paddy
Paddy

Reputation: 33867

In the case you have given above, it is hard to say what benefit you get, it would depend on how this is to be used in your code base, but consider the following:

public class Foo<T> 
    where T : IComparable
{
    private T _inner { get; set; }

    public Foo(T original)
    {
        _inner = original;
    }

    public bool IsGreaterThan<T>(T comp)
    {
        return _inner.CompareTo(comp) > 0;
    }
}

against

public class Foo             
{
    private IComparable  _inner { get; set; }

    public Foo(IComparable original)
    {
        _inner = original;
    }

    public bool IsGreaterThan(IComparable  comp)
    {
        return _inner.CompareTo(comp) > 0;
    }
}

If you then had a Foo<int>, you probably wouldn't want to compare it to a Foo<string>, but would have no way of locking that down using the non-generic version.

Upvotes: 4

Eric Lippert
Eric Lippert

Reputation: 660397

In addition to all the other good answers, I'll add that the generic version does not take the boxing penalty if you happen to construct Request<T> with a T that is a value type that implements IOperation. The non-generic version boxes every time.

Upvotes: 12

QBasicer
QBasicer

Reputation: 71

For example, if you had

public class SubOperation : IOperation 
{
    // implementation ...
}

and

public class OtherSubOperation : IOperation 
{
    // implementation ...
}

You could ensure that the Request could never hold a OtherSubOperation item, but they both would be valid IOperations.

Upvotes: 3

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174397

With the generic version a method could take a parameter of type Request<FooOperation>. Passing in an instance of Request<BarOperation> would be invalid.
So, the generic version enables methods to ensure they get a request for the correct operation.

Upvotes: 16

Related Questions