9
//this class (or interface if you like) is set up as generic...
public abstract class GenericBase<T> 
{
    public T PerformBasicTask(T in) { ... }
}

//... but is intended to be inherited by objects that close the generic...
public class ConcreteForDates:GenericBase<DateTime>
{
    public DateTime PerformSpecificTask(DateTime in) { ... }
}

//... so that consuming code never knows that a generic is involved
var myDateConcrete = new ConcreteForDates(); //look ma, no GTP!
//These two methods look alike, and there is no generic type inference,
//even with PerformBasicTask().
var basicResult = myDateConcrete.PerformBasicTask(DateTime.Now);
var specificResult = myDateConcrete.PerformSpecificTask(DateTime.Today);

//does not compile because T is understood by inheritance to be a DateTime,
//even though PerformBasicTask()'s implementation may well handle an int.
var anotherBasicResult = myDateConcrete.PerformBasicTask(1);

I've seen and used this pattern several times, and it's very useful for providing common functionality across a series of type-specific subclasses. For instance, this could be a model for Controllers/Presenters specific to a type of domain object that is central to the page(s) the class is used to control; basic operations like retrieval/persistence may use 100% common functionality, but binding/unbinding may be very specific.

Is there a name for this pattern of generic declaration without exposing the generic to the end user?

KeithS
  • 70,210
  • 21
  • 112
  • 164
  • "Closing the generic" sounds good to me. – Fantius Oct 31 '11 at 16:26
  • 1
    So why exactly would you want to do this? – Daryl Oct 31 '11 at 16:43
  • Well, for instance, you may have a set of Controllers that each take one of your domain classes (or a DTO) and perform bind/unbind/validate tasks on a View in the UI. In addition, they would also have to know how to retrieve and persist these objects. That persistence mechanism may (IMO should) be well-abstracted such that the operation can be performed by the controller using the same code. But, validation/binding/unbinding would almost certainly be very class-specific. – KeithS Oct 31 '11 at 16:57
  • 1
    So, you'd define a ControllerBase that had the generic persistence logic, and then at the derived level, since you know exactly the class you can work with, close the generic and specify your type-specific logic. – KeithS Oct 31 '11 at 16:58

3 Answers3

3

I believe this is not a pattern but specifics of Generic Type subsystem of the .NET Framework which generates concrete type in runtime by substituting generic type parameter by a concrete type (in your example DateTime). All other things regarding sharing a common behaviour is known as Inheritance

sll
  • 61,540
  • 22
  • 104
  • 156
3

If I were to name it, I would call it Specifics and I agree with Aliostad in that it is an anti-pattern.

Austin Salonen
  • 49,173
  • 15
  • 109
  • 139
  • Could you please answer stackoverflow.com/questions/9447865/… too? Is that question shows correct usage of generics or anti pattern? – LCJ Feb 26 '12 at 04:49
2

Generics is used to re-use a behaviour that needs to be described beyond the type - or at least within the restrictions enforced by the where clause.

The example you have seen, IMHO, is a generics anti-pattern. Type should not matter or if it does, should only matter if it is defined in the restrictions - i.e. where clause.

So basically, a generic abstract class which expects all subclasses to implement an abstract, is not using the genericness. I cannot just simply start using Generic<MyType> which is the point of generics.

I believe that defeats the point.

In this case there is a slight benefit in using a generic abstract class/interface and that is type safety achieve for PerformSpecificTask.


UPDATE

I knew it is a contentious issue and I would be fired at left and right, but I believe it is the case.

A class can happily subclass a generic class and add more functionality. But in this case, it is the extra functionality that defines the identity of that class. When I cannot just say Generic<MyOwnTypeOfVolition> then I have defeated the objective of generics. Sometimes, however, it is not the generics which I am concerned with - it is the interface which seems to be the case here.


UPDATE 2

A classic example, is IConvertible in .NET Framework.

You could setup a generic interface/abstract class for it and ask all subclasses to implement it, but the framework makes it an optional case and supports it only for classes implementing the interface.

Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • I have to say that I really am strongly against this type of thinking. The problem is not that one is allowed to do this in C#, it's rather that C# doesn't have a larger and more orthogonal system for generics. An abstract base class is underspecified in terms of behavior. I see no reason why it can't also be underspecified in terms of types, to be filled in by the derived classes. – siride Oct 31 '11 at 16:27
  • 2
    What, so implementing a non-generic collection by inheriting from [Collection](http://msdn.microsoft.com/en-us/library/ms132397.aspx#inheritanceContinued) is an anit-pattern? – Justin Oct 31 '11 at 16:28
  • So if I have a CustomerPageController and a PersonPageController, which work with Customer and Person objects respectively, and I have a Repository behind the scenes that can handle either object generically but the validation would be totally different, then I can't expose a Save() method from a generic base while implementing my own type-specific Validate()? – KeithS Oct 31 '11 at 16:30
  • 1
    Regarding the edit: the problem here is that C# has no way to have "abstract generics" where filling in the type is also part of the contract. We get around that with documentation. The fault does not lie with the programmer for using this pattern, but with the language for failing to provide a suitable mechanism for implementing it. – siride Oct 31 '11 at 16:30
  • @Justin inheriting is not per se anti-pattern. The fact that you have to use your subclass rather than `Collection` is the ant-pattern. – Aliostad Oct 31 '11 at 16:30
  • As I explained, there is a **slight benefit** and that is the type safety. That is all - it is not generics. – Aliostad Oct 31 '11 at 16:32
  • @Aliostad: why is it an anti-pattern to have to use a subclass? Tell me, what is the difference between providing a generic implementation in a base class to be filled in by the derived classes (the template pattern) and doing the same with types? You are creating an arbitrary distinction here that only exists because C# isn't expressive enough to let you say the right thing. – siride Oct 31 '11 at 16:32
  • I still disagree with your edit. What is the difference between complaining about not being able to use the base class with any type (which, by the way, you can do by making your own subclass) and not being able to use an abstract base class directly? It's the same problem. The base class is not intended to be used directly. – siride Oct 31 '11 at 16:51