Are there drawbacks to the generic-implementing-non-generic-interface pattern? - c#

I'm starting to see this pattern appear often in my code:
class Foo { }
interface IBar
{
Foo Foo { get; }
}
class Bar<TFoo> : IBar where TFoo : Foo
{
public TFoo Foo { get; private set; }
Foo IBar.Foo
{
get
{
return Foo;
}
}
}
Some of its benefits are:
An easy way to check whether an object is of the wrapping type (if (something is IBar))
Strong-typed access to TFoo in closed-constructed Bar<>s
Polymorphic access to Foo in interfaced IBars
One could argue that this kind of pattern is everywhere in the framework (e.g. List<T> : IList), but I wonder if this is just a remnant of .NET 1.0, when generics didn't exist.
Off the top of my head, my main concern is that IBar is not necessarily a proper contract that defines what members a "bar" should provide; it's only a hack to access generically typed members.
Also, if I start adding interfaces for that purpose, I quickly end up with hard to maintain parallel inheritance hierarchies.
Should I be worried about spreading this pattern in my code base? If so, what alternative patterns would provide some or all of the 3 benefits listed above?
Because explicitly implementing abstract members is not allowed, this "ideal" solution is not possible:
class Foo { }
class Bar
{
public abstract Foo Foo { get; }
}
class Bar<TFoo> : Bar where TFoo : Foo
{
private TFoo foo;
Foo Bar.Foo
{
get
{
return foo;
}
}
public new TFoo Foo
{
get
{
return foo;
}
}
}

For me, the summary is you shouldn't think that you implement interfaces just for the sake of augmenting a generic type parameter with more typing.
AFAIK, you use interfaces to provide which are the contracts to work with a given API. Generics are just a language feature/tool to provide more typing where you would end up doing a lot of casts. Hereby, with generics you limit your API to expect arguments implementing one or more interfaces and also with some requirements using generic constraints.
For example, if you just want to accept implementations of given interface called IWhatever, would you use generics?
public void DoStuff<T>(T whatever)
where T : IWhatever
{
}
// versus
public void DoStuff(IWhatever whatever)
{
}
BTW, without generics, how you would check that an implementation to IWhatever is a class and has a public constructor? You would end up with reflection and you're code would smell compared to using generics:
public void DoStuff<T>()
where T : class, IWhatever, new()
{
}
In fact, a generic parameter can constraint that T must inherit a given class and implement one or more interfaces:
public void DoStuff<T>(T arg)
where T : A, IEquatable<T>, IWhatever, IWhichever, IWherever
{
}
And whether if T inherits a type with or without generic parameters or implements interfaces with or without generic parameters, it's not a good or bad design per se but, again, just a language tool that's suitable to specific cases.
Therefore, your statement...
Off the top of my head, my main concern is that IBar is not
necessarily a proper contract that defines what members a "bar" should
provide; it's only a hack to access generically typed members.
...describes a particular design flaw instead of an actual problem with typing generics using the wonders of interfaces.
Conclusion: if IBar isn't a proper contract, then you should revisit your architecture and re-think your solution.
More background on the topic
Actually I thought that my original answer implied that I found the whole solution has a design flaw.
In summary, you're using interfaces to expose an association on certain classes which provide the type of the whole association using a generic type parameter. And you argue that you do this to be able to access such association in a less typed context:
However, I sometime need a "less" typesafe context, hence my question.
And then it's when covariance enters in action! See the following code sample:
public class SuperClass
{
}
public interface IWhatever<out TAssociation>
where TAssociation : SuperClass
{
TAssociation Association { get; }
}
public class SomeImplementation<TAssociation> : IWhatever<TAssociation>
where TAssociation : SuperClass
{
public TAssociation Association { get; set; }
}
Now let's define a derived class of SuperClass:
public class DerivedClass : SuperClass
{
}
And see how this works like a charm:
SomeImplementation<DerivedClass> someImpl = new SomeImplementation<DerivedClass>();
// Covariance: you decide the degree of specialization of TAssociation
// interfaces' type parameter. In our case, we'll upcast TAssociation to
// the SuperClass type.
IWhatever<SuperClass> whatever = someImpl;
Clearly this is the way to go since C# 4.0.
I would say that the right way of expressing your requirement is you need a less specialized context instead of a less typed context. Covariance/contravariance is one of the most powerful features available in C# to cover this scenario when generics are involved in the equation.
This practice isn't a code smell per se. In my case, I go for it when I really need to access one or more associations somewhere where I just need to access certain members with a concrete purpose.
For example, if I'm building a tree-style hierarchy, I would define an interface like this:
public interface IHasParent<out TParent>
{
TParent Parent { get; }
}
Which enables me to do this:
IHasParent<object> withParent = someObject as IHasParent<object>;
if(withParent != null)
{
// Do stuff here if some given object has a parent object
}
But I don't create interfaces indiscriminately because some day I'll need less typed access to some properties. There should be a well defined purpose. Otherwise, you can end up turning a nice solution into a code smell.
You would say don't repeat yourself but I still feel that there's no definitive answer without analyzing your project code base and checking how you really use this kind of interfaces to solve concrete problems.
So, strictly talking, if you use the whole pattern when it's really required, it should be a good design decision.
Maybe you want to avoid the unavoidable
Based on some chat we've had both the OP and me, I feel that the best conclusion is that the OP wants to avoid the unaviodable.
In an object-oriented language like C# interfaces are the right tool to both define type contracts and expose a subset of a full type implementing some interface.
Also, the OP would love a feature in C# like protocols where a class that implicitly fullfils an interface is enough to consider that it implements the interface which would save up many code lines if C# could have this feature:
public interface IWhatever
{
void DoStuff();
}
public class X
{
void DoStuff();
}
public class Y
{
public void HandleStuff(IWhatever whateverImpls)
{
}
}
Y y = new Y();
// Protocols would support passing an instance of X which may not implement
// IWhatever but it implicitly fulfills IWhatever:
y.HandleStuff(new X());
BTW, C# lacks this feature. Therefore, it's a waste of time scratching your head thinking how sweet would be having such feature. You need to deal with what C# has to offer already.
Anyway, if you just need to expose some associations across your object graph and get them selectively, you can use the wonders of interfaces using a more simplified approach than yours. Did you know that you can explicitly implement the same interface more than once if its generic arguments vary?
Why don't you design an interface like this:
public interface IHasAssociation<out TAssociation>
{
TAssociation Association
{
get;
}
}
public interface IHasManyAssociation<out TEnumerable, out TAssociation>
where TEnumerable : IEnumerable<TAssociation>
where TAssociation : Entity
{
TEnumerable Association
{
get;
}
}
public class Entity
{
}
public class Company : Entity
{
}
public class CustomerProfile : Entity
{
}
public class Contact : Entity
{
}
public class Customer :
IHasAssociation<Company>,
IHasAssociation<CustomerProfile>,
IHasManyAssociation<IList<Contact>, Contact>
{
public Company Company
{
get;
set;
}
public CustomerProfile Profile
{
get;
set;
}
public IList<Contact> Contacts
{
get;
set;
}
Company IHasAssociation<Company>.Association => Company;
CustomerProfile IHasAssociation<CustomerProfile>.Association => Profile;
IList<Contact> IHasManyAssociation<IList<Contact>, Contact>.Association => Contacts;
}
Definitively this keep things simpler (KISS!) because you don't need a parallel interface object graph definition, you simply define an interface to being able to get an association of a given type:
var customer = new Customer();
customer.Profile = new CustomerProfile();
customer.Company = new Company();
customer.Contacts = new List<Contact>();
var withCompany = customer as IHasAssociation<Company>;
var withCustomerProfile = customer as IHasAssociation<CustomerProfile>;
var withContacts = customer as IHasManyAssociation<IList<Contact>, Contact>;
if (withCompany != null)
{
Company company = withCompany.Association;
Console.WriteLine("This object has an associated company!");
}
if (withCustomerProfile != null)
{
CustomerProfile profile = withCustomerProfile.Association;
Console.WriteLine("This object has a profile!");
}
if (withContacts != null)
{
IList<Contact> contacts = withContacts.Association;
Console.WriteLine("This object has contacts!");
}
Also, see covariance in action:
if(customer is IHasManyAssociation<IEnumerable<Contact>, Contact>)
{
Console.WriteLine("This object has an enumerable of contacts!");
}
Or here's how you would get all association values of an implementor of one or many IHasAssociation<out TAssociation> interface implementations:
var entityAssociations = typeof(Customer)
.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IHasAssociation<>))
.Select(i => i.GetProperty("Association").GetValue(customer));
foreach(var entityAssociation in entityAssociations)
{
Console.WriteLine($"{entityAssociation.GetType().FullName}");
}
This is the real beauty of generic programming! And remember: you won't need to implement IHasAssociation<out TAssociation>/IHasManyAssociation<out TEnumerable, out TAssociation> indiscriminately. That is, you implement on the classes to which associations need to be extracted in some place where you don't care who's the concrete owner of the association and you just need the association itself.

In your question, you express the need for a "generic" wrapper type (note I use the term "generic" here independently of any language).
Well, I don't see any problem with that. And if you ask me how to do it with .NET, I would just design this, once for all types, going one step further from you:
interface IWrapper<T>
{
T BaseObject { get; }
}
Then, a wrapper class would simply be:
class Bar<TFoo> : IWrapper<TFoo> where TFoo : Foo
{
public TFoo BaseObject { get; private set; }
}
I could go further again and define the non generic one, because it's ofen desirable to have both, as it's sometimes hard to work with generic-only clases/interface with meta/reflection code (but this is really optional):
interface IWrapper
{
object BaseObject { get; }
}
If you do this, it could be natural to have IWrapper<T> derive from IWrapper, like this:
interface IWrapper<T> : IWrapper
{
new T BaseObject { get; }
}
And the class would be this:
class Bar<TFoo> : IWrapper<TFoo> where TFoo : Foo
{
public TFoo BaseObject { get; private set; }
object IWrapper.BaseObject => BaseObject;
}
PS: as a side note, you can have a look at WCF's ServiceModel ChannelFactory<T> class that has a combined generic/non generic hierarchy somewhat relevant with your question.

I've found myself in a similar place after developing an API.
I have some questions for you and no answers.
But once you can answer those questions, maybe you know a bit more about how to address this situation.
I wonder how many classes implement IBar.
Are there enough to justify it?
Is this an API and you expose it to client code?
In how many code points do you leverage the polymorphism of the interface?
Just maybe... those answers can make you question the interface's usefulness.
How many times does this structure emerge?
And are you sure it actually does?
I mean, you say you did this:
implement lots of code (A);
refactor it in one place to clean it up;
implement more code (B);
refactor it to clean it up;
notice that B looks similar to A;
implement more code (C);
refactor it to clean it up;
notice that C looks similar to B (by transitivity also to A);
repeat...
Did the structure REALLY emerge, or is it your thinking that mold the code always in the same way?
Which comes first?
the emergence;
the thinking.
This "rinse" and "repeat" approach may be good to start, but just maybe... you've grown out of this methodology and should approach another one:
First design, then implement.
Is this your case? Have you grown that much, that you can finally approach design before implementation?
There's a saying that may apply here:
When you have a hammer, everything looks like a nail.
But let's assume this is not your case.
You don't fall into thought cycles and the underlying problem REALLY has this structure, thus your code reflects the problem's structure.
If you really came up with the same thing multiple times, but it's the problem, not your mind playing tricks, then the following may be a good advice.
Stop coding for a day, and think about it away from keyboard.
Which parts are the same, which different?
Can't you implement this in an even MORE abstract way (actual pattern) into which you inject the specialized code?
Maybe, underlying it all, is a something as simple as a composite pattern, and you could just implement that once and for all, and then reuse it all over the place.
What happened to me was similar, and I ended up with a dependency injection, an abstract factory, an abstract implementation of the composite pattern and an information expert, which took a configuration file and assembled the final object graphs I needed.
It was an excellent, humbling lesson in patterns and architecture, but I regretted actually using it.
Writing the documentation was near impossible and futile.
The code became extremely difficult to follow.
I always had to look things up and rethink about how to use it correctly.
The end result was not that astonishing.
So, if you want to learn and exercise, don't ever stop!
But if you want to just get it done and move on, don't overthink it.
Simple is better!
You may be in a place where you try to perfect your code but actually don't need it.
You're not writing a new API for M$, are you?
Just take this advice:
In a year or two, you won't be able to understand your own code. You must document it, if you make it that complex. If you can't document it, you'll never reuse it. So you don't need this perfection, it will be throw-away code.
In other words:
The real value is not the code, but the documentation that accompanies it. Without documentation there will be no reuse..

In retrospect, I've learned that the correct term for what I want is return type covariance, which is unfortunately not supported in C#, because the language design team does not consider the benefits of implementing the feature outweigh the cost, even though it preserves type safety. (A proposal has been drafted and completed, but it seems to be abandoned).
With return type covariance, the example code could be written as:
class Foo { }
class Bar
{
public virtual Foo Foo { get; }
}
class Bar<TFoo> : Bar where TFoo : Foo
{
public override TFoo Foo { get; }
}
The workaround proposed by Eric Lippert in that linked question is:
class Foo { }
abstract class Bar
{
protected abstract Foo foo { get; }
public Foo Foo => foo;
}
class Bar<TFoo> : Bar where TFoo : Foo
{
protected override Foo foo => this.Foo;
public new TFoo Foo { get { ... } }
}
It has the downside of duplicating not the inheritance hierarchy, but every covariant-simulated property per level of inheritance!
For further reading on how much clutter simulating covariant return types can bring to your code, consider that implementing ICloneable properly implies adding another virtual method per level of inheritance. I'll leave this as my humble plea for that language feature.

Related

Unable to cast object of type 'Parent' to type 'Child' [duplicate]

I'm not sure if this is a strange thing to do or not, or if it is some how code smell...but I was wondering if there was a way (some sort of oop pattern would be nice) to "cast" a base type to a form of its derived type. I know this makes little sense as the derived type will have additional functionality that the parent doesn't offer which is in its self not fundamentally sound. But is there some way to do this? Here is a code example to so I can better explain what I"m asking.
public class SomeBaseClass {
public string GetBaseClassName {get;set;}
public bool BooleanEvaluator {get;set;}
}
public class SomeDerivedClass : SomeBaseClass {
public void Insert(SqlConnection connection) {
//...random connection stuff
cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
//...
}
}
public static void Main(object[] args) {
SomeBaseClass baseClass = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)baseClass;
derClass.Insert(new sqlConnection());
}
I know this seems goofy but is there any way to accomplish something of this sort?
Not soundly, in "managed" languages. This is downcasting, and there is no sane down way to handle it, for exactly the reason you described (subclasses provide more than base classes - where does this "more" come from?). If you really want a similar behaviour for a particular hierarchy, you could use constructors for derived types that will take the base type as a prototype.
One could build something with reflection that handled the simple cases (more specific types that have no addition state). In general, just redesign to avoid the problem.
Edit: Woops, can't write conversion operators between base/derived types. An oddity of Microsoft trying to "protect you" against yourself. Ah well, at least they're no where near as bad as Sun.
Try composition instead of inheritance!
It seems to me like you'd be better off passing an instance of SomeBaseClass to the SomeDerivedClass (which will no longer derive base class, and should be renamed as such)
public class BooleanHolder{
public bool BooleanEvaluator {get;set;}
}
public class DatabaseInserter{
BooleanHolder holder;
public DatabaseInserter(BooleanHolder holder){
this.holder = holder;
}
public void Insert(SqlConnection connection) {
...random connection stuff
cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
...
}
}
public static void Main(object[] args) {
BooleanHolder h = new BooleanHolder();
DatabaseInserter derClass = new DatabaseInserter(h);
derClass.Insert(new sqlConnection);
}
Check out http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (page 3):
Code reuse via composition Composition
provides an alternative way for Apple
to reuse Fruit's implementation of
peel(). Instead of extending Fruit,
Apple can hold a reference to a Fruit
instance and define its own peel()
method that simply invokes peel() on
the Fruit.
Personally I don't think it's worth the hassle of using Inheritance in this case. Instead just pass the base class instance in in the constructor and access it through a member variable.
private class ExtendedClass //: BaseClass - like to inherit but can't
{
public readonly BaseClass bc = null;
public ExtendedClass(BaseClass b)
{
this.bc = b;
}
public int ExtendedProperty
{
get
{
}
}
}
Downcasting makes sense, if you have an Object of derived class but it's referenced by a reference of base class type and for some reason You want it back to be referenced by a derived class type reference. In other words You can downcast to reverse the effect of previous upcasting. But You can't have an object of base class referenced by a reference of a derived class type.
I'm not saying I recommend this. But you could turn base class into JSON string and then convert it to the derived class.
SomeDerivedClass layer = JsonConvert.DeserializeObject<SomeDerivedClass>(JsonConvert.SerializeObject(BaseClassObject));
No, this is not possible. In a managed language like C#, it just won't work. The runtime won't allow it, even if the compiler lets it through.
You said yourself that this seems goofy:
SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class;
So ask yourself, is class actually an instance of SomeDerivedClass? No, so the conversion makes no sense. If you need to convert SomeBaseClass to SomeDerivedClass, then you should provide some kind of conversion, either a constructor or a conversion method.
It sounds as if your class hierarchy needs some work, though. In general, it shouldn't be possible to convert a base class instance into a derived class instance. There should generally be data and/or functionality that do not apply to the base class. If the derived class functionality applies to all instances of the base class, then it should either be rolled up into the base class or pulled into a new class that is not part of the base class hierarchy.
C# language doesn't permit such operators, but you can still write them and they work:
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) { ... }
[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) { ... }
Yes - this is a code smell, and pretty much nails down the fact that your inheritance chain is broken.
My guess (from the limited sample) is that you'd rather have DerivedClass operate on an instance of SomeBaseClass - so that "DerivedClass has a SomeBaseClass", rather than "DerivedClass is a SomeBaseClass". This is known as "favor composition over inheritance".
As others have noted, the casting you suggest is not really possible.
Would it maybe be a case where the Decorator pattern(Head First extract) can be introduced?
Have you thought about an interface that what is currently your base class and your derived class both would implement? I don't know the specifics of why you're implementing this way but it might work.
This is called downcasting and Seldaek's suggestion to use the "safe" version is sound.
Here's a pretty decent description with code samples.
This is not possible because how are you going to get the "extra" that the derived class has. How would the compiler know that you mean derivedClass1 and not derivedClass2 when you instantiate it?
I think what you are really looking for is the factory pattern or similar so you can instantiate objects without really knowing the explicit type that's being instantiate. In your example, having the "Insert" method would be an interface that instance the factory returns implements.
I dont know why no one has said this and i may have miss something but you can use the as keyword and if you need to do an if statement use if.
SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
;
-edit- I asked this question long ago
I've recently been in the need of extending a simple DTO with a derived type in order to put some more properties on it. I then wanted to reuse some conversion logic I had, from internal database types to the DTOs.
The way I solved it was by enforcing an empty constructor on the DTO classes, using it like this:
class InternalDbType {
public string Name { get; set; }
public DateTime Date { get; set; }
// Many more properties here...
}
class SimpleDTO {
public string Name { get; set; }
// Many more properties here...
}
class ComplexDTO : SimpleDTO {
public string Date { get; set; }
}
static class InternalDbTypeExtensions {
public static TDto ToDto<TDto>(this InternalDbType obj) where TDto : SimpleDTO, new() {
var dto = new TDto {
Name = obj.Name
}
}
}
I can then reuse the conversion logic from the simple DTO when converting to the complex one. Of course, I will have to fill in the properties of the complex type in some other way, but with many, many properties of the simple DTO, this really simplifies things IMO.
That cannot work. Go look at the help page linked by the compile error.
The best solution is to use factory methods here.
As many answers have pointed out, you can't downcast which makes total sense.
However, in your case, SomeDerivedClass doesn't have properties that will be 'missing'. So you could create an extension method like this:
public static T ToDerived<T>(this SomeBaseClass baseClass)
where T:SomeBaseClass, new()
{
return new T()
{
BooleanEvaluator = baseClass.BooleanEvaluator,
GetBaseClassName = baseClass.GetBaseClassName
};
}
So you aren't casting, just converting:
SomeBaseClass b = new SomeBaseClass();
SomeDerivedClass c = b.ToDerived<SomeDerivedClass>();
This only really works if all of the data in the base class is in the form of readable and writable properties.
C++ handles it using a constructor. C++ Typecasting. It seems like an oversight to me. Many of you have brought up the issue of what would the process do with the extra properties. I would answer, what does the compiler do when it creates the derived class when the programmer does not set the properties? I have handled this situation similar to C++. I create a constructor that takes the base class then manually set the properties in the constructor. This is definitely preferable to setting a variable in the derived class and breaking the inheritance. I would also choose it over a factory method because I think the resulting code would be cleaner looking.

Is letting a class pass itself as a parameter to a generic base class evil?

I first saw a colleague do this when he implemented object pools. He passed the class that was going to be pooled as a parameter to a generic base class. This base class layed out the pooling code.
The odd thing is that the base class will know of its children. This is considered bad practice in every normal case. But in this case the parent is just a technical solution to avoid writing repetetive code. The base class is never referenced by any other code.
One drawback with this construction is that it "burns the base class". You cannot introduce the generic base class in the middle of a hierarchy. This problem might be outside the topic.
Below is a thinkable example:
public abstract class Singleton<T> where T : class
{
public static T Instance { get; private set; }
public Singleton()
{
if (Instance != null)
throw new Exception("Singleton instance already created.");
Instance = (T) (object) this;
}
}
public class MyClass : Singleton<MyClass>
{
}
Improved code:
public abstract class Singleton<T> where T : Singleton<T>
{
public static T Instance { get; private set; }
public Singleton()
{
if (Instance != null)
throw new Exception("Singleton instance already created.");
Instance = (T) this;
}
}
public class MyClass : Singleton<MyClass>
{
}
No; this is a well-known pattern called the CRTP.
It is especially useful in C++ as an alternative to virtual methods.
You can see it inside the .Net framework in IComparable<T> and IEquatable<T>.
For added robustness, you should add where T : Singleton<T>
SLaks is correct - this is a useful pattern, generally for when you want to provide code in your base class which is strongly typed to your derived class.
You would also generally add a type constraint to the generic parameter to indicate that the generic type must inherit from the abstract type. The syntax for adding this constraint looks recursive, but don't panic about that - it is not evaluated recursively and simply ensures that the only valid generic types are derived classes.
For example, let's say you run a tea and coffee blending business. It makes sense for you to blend coffee with coffee, and tea with tea, but you want to make sure that you can't blend coffee with tea. However, as they are both beverages, you want to model them in the same way.
public abstract class Beverage<T> where T : Beverage<T>
{
public abstract T Blend(T drink1, T drink2);
}
public class Tea : Beverage<Tea>
{
public override Tea Blend(Tea drink1, Tea drink2)
{
// Blend tea here.
}
}
public class Coffee : Beverage<Coffee>
{
public override Coffee Blend(Coffee drink1, Coffee drink2)
{
// Blend coffee here. Although coffee is nasty, so
// why you'd want to is beyond me.
}
}
When reading about CRTP, it is worth remembering that C++ templates are only superficially similar to C# generics. The key difference is that templates are effectively a code generation tool which work at compile-time, whereas C# generics are supported at run time.
Furthermore, writing code like this can reduce readability. So although there are definitely instances where this would be the correct approach, you should take a think about the problem you're trying to solve and see if there's a more straightforward approach.

Interface and class inheritance. Is this an avoidable pattern?

I'd appreciate any advice on which way to go on in the following scenario. Let's see if I can explain it clearly (english is not my native language so things might get confusing, sorry).
Suppose I have the following interfaces:
internal interface IBlah
{
int Frob();
}
internal interface IBlahOnSteroids: IBlah
{
double Duh();
}
Now we have a Foo class with a 'has a' relationship with an IBlah object:
public class Foo
{
IBlah blah;
internal Foo(IBlah blah)
{
this.blah = blah;
}
public int Frob()
{
....
return this.blah.Frob();
}
}
Now we also need a FooOnSteroids class that has a 'has a' relationship with a IBlahOnSteroids object.
The question is, knowing that part of IBlahOnSteroids is already implemented in Foo, what happens if we create
FooOnSteroids inheriting from Foo?
We would get something like this:
public class FooOnSteroids: Foo
{
IBlahOnSteroids blah;
internal FooOnSteroids(IBlahOnSteroids blah)
:base(blah)
{
this.blah = blah;
}
public double Duh()
{
return this.blah.Duh();
}
}
Is this a recommended pattern? We are passing down the inheritance chain the same 'blah' object and at each "level" we are storing it in a private
field with a 'useful' type. There is no way, that I can see, that I could store in BlahBase a protected property that
exposed one common IBlah reference to all descending classes as it would have to be of type IBlah wich would be of no use to BlahOnSteroids. Is this scenario even
recommended? Or should we just implement Foo and FooOnSteroids as independent classes with no inheritance (this would create code duplication)? Maybe its absolutely fine to do this, but it somehow feels like a hack. Is it?
The option of using generics, which would solve the problem in no time, is not possible as, yes I know it sucks, this library must target .Net 1.x platforms.
The option of just implementing BlahOnSteroids is also a possibility but it would mean that depending on the caller, we would have to throw an exception if any of
IBlahOnSteroids members was called. I dont like that.
Thanks a lot for any advice!
You could reduce the duplication by making the base field available:
IBlah blah;
protected IBlah Blah { get { return blah; } }
and cast at the sub-type (since you expect your choice of blah to be respected):
public double Duh() {
return ((IBlahOnSteroids)Blah).Duh();
}
You could also do something with generics on the base-type (to avoid the cast) but I'm not sure it is worth it. Note, however, that this might explode if the base-class decides to inject a decorator abound blah (if the decorator doesn't provide the second interface).
One alternative pattern is
public class Foo
{
protected IBlah Blah { get; private set; }
...
}
public class FooOnSteroids : Foo
{
private new IBlahOnSteroids Blah { get { return (IBlahOnSteroids)base.Blah; } }
...
}
However, this isn't very different from your code; if you can't use generics, they're both fine.
In response to your question about removing the inheritance between Foo and FooOnSteroids, I don't know all your reasoning, but I can try to provide some general guidance. You should consider using inheritance mainly to provide your clients the ability to use FooOnSteroids instances, but only write the code for Foo.
So, if conceptually your clients do this:
Foo foo = new FooOnSteroids();
foo.Frob()
you should keep the inheritance.
If you are creating the inheritance relationship ONLY to re-use code, I suggest you consider refactoring the classes to contain a class which provides the shared functionality. Inheritance is not the best pattern for code re-use.
Given that you can't use generics (which may or may not make your specific use case easier) I would personally opt for casting the blah member of Foo. Casting in C# is relatively painless:
public double Duh()
{
return (this.blah as IBlahOnSteroids).Duh();
}
The as keyword in C# will evaluate to null if the object can't be cast into the type you requested. In the above example, if this.blah isn't an instance of IBlahOnSteroids you will get a NullReferenceException. You can check if an object is an instance of a type like so:
public double Duh()
{
if (this.blah is IBlahOnSteroids)
return (this.blah as IBlahOnSteroids).Duh();
else
throw new InvalidTypeException("Blah is not an instance of IBlahOnSteroids");
}
Though in the code in your original example it shouldn't be possible for blah to not be an instance of IBlahOnSteroids since it's assigned in the constructor, which makes that assertion at compile time for you.

Dealing with multiple generics in a method call

I've been dealing a lot lately with abstract classes that use generics. This is all good and fine because I get a lot of utility out of these classes but now it's making for some rather ugly code down the line. For example:
abstract class ClassBase<T>
{
T Property { get; set; }
}
class MyClass : ClassBase<string>
{
OtherClass PropertyDetail { get; set; }
}
This implementation isn't all that crazy, except when I want to reference the abstract class from a helper class and then I have to make a list of generics just to make reference to the implemented class, like this below.
class Helper
{
void HelpMe<C, T>(object Value)
where C : ClassBase<T>, new()
{
DoWork();
}
}
This is just a tame example, because I have some method calls where the list of where clauses end up being 5 or 6 lines long to handle all of the generic data. What I'd really like to do is
class Helper
{
void HelpMe<C>(object Value)
where C : ClassBase, new()
{
DoWork();
}
}
but it obviously won't compile. I want to reference ClassBase without having to pass it a whole array of generic classes to get the function to work, but I don't want to reference the higher level classes because there are a dozen of those. Am I the victim of my own cleverness or is there an avenue that I haven't considered yet?
I suppose that your HelpMe method would be used for initializing the concrete ClassBase<T> type (a guess based on the constraints). To keep the code fully generic (if you need both T and C somewhere in the method), you probably need to keep both of the type parameters.
However, you could add a non-generic base class and then write something like this:
abstract class ClassBase {
object UntypedProperty { get; set; }
}
abstract class ClassBase<T> : ClassBase {
T Property { get; set; }
public override object UntypedProperty {
get { return Property; }
set { Property = (T)value; }
}
}
Then you could be to write the helper method like this:
void HelpMe<C>(object Value) where C : ClassBase, new() {
var n = new C();
c.UntypedProperty = Value;
}
Depending on your specific scenario, something along these lines might work and make the code a little bit simpler. However, you need to modify the base class to make this possible.
Generics do have a tendency to propogate through the code, and they're seldomly used as "mixin" classes for that reason.
Thomas mentioned the one possibility of introducing an equivalent non-generic API. I would prefer revisiting the design and making these base classes non-generic if possible while maintaining full type safety. Whether or not this is actually possible is determined by your requirements.
There is one other possibility short of a re-design (or API duplication): dynamic. If you're willing to lose IntelliSense in your helper methods (and are willing to pay a very, very small runtime performance penalty), you can use dynamic in your helper method:
class Helper
{
void HelpMe<C>(object Value)
// where C : ClassBase<T>, new() // no longer needed, but should be documented
{
dynamic cObj = Activator.CreateInstance<C>(); // instead of "new C()"
cObj.PropertyDetail = ...;
cObj.Property = ...;
...
}
}
without having to pass it a whole array of generic classes to get the function to work
A small change might ease these calls. Move repeatedly specified types to the generic declaration of the class.
//before
Helper x = new Helper();
x.HelpMe<MyClass, string>(x);
x.HelpMe<MyClass, string>(y);
//after
Helper x = new Helper<string>();
x.HelpMe<MyClass>(x);
x.HelpMe<MyClass>(y);
//the change
class Helper<T>
{
void HelpMe<C>(object Value)
where C : ClassBase<T>, new()
{
DoWork();
}
}

How To Implement Shared Behavior Between Classes (Without Multiple Inheritance Of Course) in C#

UPDATE:
So pretty much everyone here has told me that I just need to start all over again on how I designed my classes (thank you folks for your excellent answers by the way!). Taking the hint, I started doing extensive reading on the strategy pattern. I want to create behavior classes (or strategy classes) that inherit from an abstract base class or classes. The Candidate class would then have properties w/ the different abstract base class/classes as the Type for the behaviors or strategies. maybe something like this:
public abstract class SalaryStrategy {
public abstract decimal Salary { get; set; }
public abstract decimal Min { get; set; }
public abstract decimal Mid { get; set; }
public decimal CompaRatio {
get {
if (this.Mid == 0) { return 0; }
else { return this.Salary / this.Mid; }
}
}
}
public class InternalCurrentSalaryStrategy {
public override decimal Salary { get; set; }
public override decimal Min {
get { return this.Salary * .25m; }
set { }
}
public override decimal Mid { get; set; }
}
public class Candidate {
public int Id { get; set; }
public string Name { get; set; }
public SalaryStrategy CurrentSalaryStrategy { get; set; }
}
public static void Main(string[] args) {
var internal = new Candidate();
internal.CurrentSalaryStrategy = new InternalCurrentSalaryStrategy();
var internalElp = new Candidate();
internalElp.CurrentSalaryStrategy = new InternalCurrentSalaryStrategy();
var elp = new Candidate();
// elp.CurrentSalaryStrategy can stay null cause it's not used for elps
}
Any comments or suggestions?
ORIGINAL Question:
I am trying to learn and become more proficient at design patterns and principles. I have am currently working on a design for few classes that has stumped me. Here's a very condensed version of the code:
public class Candidate {
public int Id { get; set; }
public string Comments { get; set; }
// lots more properties and behaviors...
}
public class InternalCandidate : Candidate {
public decimal CurrentMid { get; set; }
public decimal CurrentMax {
get { return this.CurrentMin * 1.3m;
}
// lots more properties and behaviors...
}
public class EntryLevelCandidate : Candidate {
public string Gpa { get; set; }
// lots more properties and behaviors...
}
public class InternalEntryLevelCandidate /* what do I inherit here??? */ {
// needs all of the properties and behaviors of
// EntryLevelCandidate but also needs the CurrentMin and
// CurrentMax (and possibly more) in InternalCandidate
}
The InternalEntryLevelCandidate class is primarily an EntryLevelCandidate but needs to share some of the implementations of InternalCandidate. I say implementations because I don't want the implementations to be different or repeated, otherwise I would use an interface for common contracts and have concrete implementations in each class. Some of the implementations of the InternalCandidate properties and behaviors need to be common or shared. I have read about C++ and Ruby mixins, which seem to be something similar to what I want to do. I also read this interesting blog post that discusses an idea for a behavior type where a class would be able to inherit multiple behaviors while still maintaining a single "is a" relationship: http://www.deftflux.net/blog/post/A-good-design-for-multiple-implementation-inheritance.aspx. This seems to convey what I am wanting. Can anyone give me some direction on how I can accomplish this using good design practices?
Immutable data value classes. If any properties in your various Candidate subclasses represent some kind of meaningful data value, create an immutable class for it, with the behaviors you need. Each of your distinct Candidate subclasses can then use the data type, but your code is still encapsulated in the data classes.
Extension methods. These could be overloaded to work with any classes.
I'd avoid the decorator pattern and stick with compiled/reflectable functionality.
Composition. Develop the unique behaviors in separate classes right away, and build your Candidate classes around them, rather than writing unique behaviors in your Candidate classes and trying to pull out their functionality for use in related classes later.
Depending on how you use the classes, you could also implement and make use of explicit and implicit conversion operators to a related type, so instead of reimplementing interfaces (which you wanted to avoid), you could actually cast your object into the type/implementation you need for whatever purpose.
Another thing I just thought of, related to that last paragraph, is to have a leasing system, where your class spawns and object of the appropriate type, allows it to be manipulated, then consumes it later to assimilate the updated information.
Here's a scholarly paper on the subject that I think is pretty interesting (PDF link).
But, I think you are trying to impose business logic in your generalizations. You happen to know that an InternalCandidate will never have his GPA looked at. But, an InternalCandidate certainly has a GPA. So, you have cracked out this strange guy called an InternalEntryLevelCandidate because you happen to know that you want to look at this guy's GPA. Architecturally, I think the EntryLevelCandidate is incorrect. I would add a "Level" concept to a Candidate and give him a GPA. It's up to the business logic to decide if they look at the GPA or not.
Edit: Also, Scott Meyers does a great job of dissecting this issue in his books.
Disclaimer:
In my experience needing multiple inheritance is the exception rather than the rule, careful design of class hierarchies can usually avoid needing this feature. I agree with JP that this requirement could be avoided in your sample.
Back to the question, there is no clean solution, however you have a few options:
Use extension methods, has the disadvantage that right click Resolve does not works, also some people really dislike these puppies.
Create an aggregate object that holds and instance of each class you want composited, re-implement stub methods that delegate.
Define an interface for each behavior and have the methods in the base check if this is IInterface before executing the behavior. (allows you to pull behavior definitions to the base)
Near duplicate:
Multiple inheritance in C#
I agree that inheritance doesn't seem to be the right thing here. I'm not sure that I know the perfect answer, but perhaps the Decorator pattern is appropriate.
Another, more esoteric idea is to think about aspect-oriented programming. You can do some pretty amazing things with aspects, but it's a very advanced topic that I still haven't mastered. The kind of folks who have are like Rikard Oberg and his Qi4J cohorts.
I'd just use the Delegation pattern. Ultimately I'd use an interface for each distinct piece of functionality, then have a concrete class as a delegate for each interface. Then your final classes just use the delegates they need and can inherit from multiple interfaces.
public class InternalEntryLevelCandidate : EntryLevelCandidate {
private InternalCandidate internalCandidateDelegate
= new InternalCandidate();
public decimal CurrentMid {
get { return internalCandidateDelegate.CurrentMid; }
set { internalCandidateDelegate.CurrentMid = value; }
}
public decimal CurrentMax {
get { return internalCandidateDelegate.CurrentMax }
}
}

Categories