Difference between interface inheritance and generic constraints - c#

I have the following code in C#:
1)
public class MyBinaryTree<TItem> where TItem : IComparable<TItem>
{ ... };
2)
public class MyBinaryTree<TItem> : IComparable<TItem>
{ ... };
I found this sample at this site, but it is not entirely the way I want.
The first example/code tells us that item (TItem) implements the interface IComparable.
The second example/code tells us that our whole class (MyBinaryTree) implements the interface IComparable.
I do not understand it very well.
The first example I've never used and the second I use often (this is a classic example of the interface). Some advice - supplements?
How does it apply in practice?

The difference is that the second example is interface inheritance. The second is constraints on what the generic type can be.
Interface inheritance means that the class that inherits that interface MUST provide implementations (unless it is abstract) of the methods contained within the interface. So, this essentially imposes constraints on the class and how it is built
Constraints on the other hand, impose constraints on the generic type that is used within the class. This allows the implementation to be able to make certain assumptions as to what TItem will be allowed to do within the class.
Examples:
Inheritance
public class IComparableImplemented : IComparable<T>
{
//MUST implement CompareTo
public int CompareTo(T other)
{
//Compare stuff
}
}
Type Constraints
public class ClassUsingConstraints<T> where T : IComparable<T>
{
public static void method(T stuff)
{
stuff.CompareTo(stuff);
}
}
So, you will notice that inheritance forces the class to implement a method. Whereas type constraints do not force anything on the class implementation. Instead, type constraints force that T must implement IComparable. So, that way you can rely on T having access to the CompareTo method

The statements aren't really comparable! Pun intended
One as you say is a classic implementation, the other is saying to be a valid entry in the MyBinaryTree collection, the member must implement the interface.
public class MyBinaryTree<TItem> where TItem : IComparable<TItem>
could have easily been
public class MyBinaryTree<TItem> where TItem : int;
{
}
It's only choosing to use IComparable in both statements that is leading to your furrowed brow.

Related

Can I override the properties and functions of a generically typed interface extending a non generic interface to consider generic type(s) in C#

What I have is a non generic interface for the purpose of having a common contact that I can call functions. The interface returns objects which implement other interfaces. For example:
public interface ISearchAdvancedInputController
{
ISearchAdvancedInput GetAdvancedInput();
void LoadFromModel(ISearchAdvancedInput advancedInput);
}
I then currently have an abstract generic class which implements the interface but imposes requirements of the type. The types of the abstract class must implement the same interfaces as the interface's properties and functions demand. I cast the generic type to the implemented type when necessary so that I can satisfy the requirements of the implemented non abstract interface. This way, I can extend this abstract class and it will enforce type requirements across a larger class w/ many different types used across it. For example:
public abstract class ISearchAdvancedInputControllerBase<standardInput, advancedInputType> : ISearchAdvancedInputController
where advancedInputType : ISearchAdvancedInput
{
protected abstract advancedInputType GetAdvancedInput();
ISearchAdvancedInput ISearchAdvancedInputController.GetAdvancedInput()
{
return GetAdvancedInput();
}
void ISearchAdvancedInputController.LoadFromModel(ISearchAdvancedInput advancedInput)
{
LoadFromModel((advancedInputType)advancedInput);
}
public abstract void LoadFromModel(advancedInputType advancedInput);
}
This works really well in general however it falls short because I'm having to use an abstract CLASS in order to perform this overriding. As such when I want to actually make use of it for more concrete examples, I encounter the error that I can only extend a single class.
So to get around this I extend the "other" class in the previous base abstract class. However this is not ideal because if I wind up creating another concrete implementation I need to redefine all of the type translations that I'm doing which is NOT related to the concrete classes implementation.
What I'd like is to not have an abstract class but instead some sort of abstract interface. If I had this I'd be able to implement concrete classes more succinctly. I've looked at other instances of this question and have tried what seems to be the main suggestion which is to make the initial interface generic and have the type extend the resulting interface type and then extend that interface with the more abstract interface as such:
interface TestGenericInterface<a> where a:TestClassInterfaceA
{
TestClassInterfaceA testGeneric { get; }
}
interface TestGenericComplexInterface<a> : TestGenericInterface<a>
where a:TestClassInterfaceA
{
new a testGeneric { get; }
}
However the concrete class seems to suffer from the same issue that's shown when you start from a non generic interface where each function / property of the base interface needs overwritten.
public class TestClass : TestGenericComplexInterface<TestGC>
{
public TestGC testGeneric => I want to complete this because its return is the type that I'm wanting to use for this concrete implementation
TestClassInterfaceA TestGenericInterface<TestGC>.testGeneric => I don't want to have to complete this because this function is already handled by the previous function in a round about sense.
}
public class TestGC : TestClassInterfaceA { }
I do see a note that I could provide default implementation of functions if I use c# v8.0 or greater, so I must be on a version prior to that but I figure this should be possible w/o that, but maybe in a different way. Hope ya'll can assist.

What is usage of this recuring generic class?

This code is compiled in visual studio, what is it's usage
public class MyClass<T>
where T : MyClass<T>
Note where T : MyClass<T>
This is the recurring template pattern and is usually used so that a base class can refer to its real type statically. This is done in an attempt to preserve type-safety so that parameter or return values referred to in the base class track the current type in the hierarchy e.g
public class Animal<T> where T : Animal<T>
{
public abstract T GiveBirth();
}
public class Cat : Animal<Cat>
{
public override Cat GiveBirth() { return new Cat(); }
}
Without the type parameter the Animal base class method would only be able to define the return type of GiveBirth to be Animal, which may reduce type safety for the clients.
It may be acceptible if you control the entire hierarchy and can ensure that classes supply the correct type parameter, but note that it can be abused e.g.
public class Cat : Animal<Dog> { ... }
Another downside is that any clients need to take account of the generic type parameter if they want to be applied to the base class e.g.
public static void Feed<T>(Animal<T> animal) where T : Animal<T> { ... }
public static void Feed<T>(T animal) where T : Animal<T> { ... }
This is an example of the curiously recurring pattern. Eric Lippert has an excellent article on this, including why you should usually avoid it.
It might be extended like this:
public class MyChild : MyClass<MyChild>
The pattern doesn't really clue you as to why you want this generic. This is unlike most generics/constraints...e.g. if I have List<Giraffe> I can see the relationship; if I have MyGeneric<T, U> where T : IComparer<U>, I can see what T will do. With T : MyClass<T>, I really have no hints as to the relationships or usages here. Perhaps there's a...
abstract T Instance { get; }
...that you wish to have the stronger-typing of MyChild in the case of MyChild.
As an example of why this isn't so good, you could have MyOtherClass : MyClass<MyChild>, or you could have MyGrandchild : MyChild, neither of which are probably what you were trying to enforce.
For types which will only have a single layer of inheritance from an abstract base type, use of the described pattern will make it possible for the abstract base type to include methods which, when called on any member of a derived type, will return a member of that derived type. This can be a useful design feature, allowing for much cleaner caller code than would otherwise be possible. The biggest problem with this design is that because .NET has no support for covariant generic class parameters, the approach won't work with multiple layers of inheritance.
Given abstract class AnimalBase<T> where T:AnimalBase<T>, with method T Clone() and class Cat: AnimalBase<Cat>, code could say var newCat = someCat.Clone(); newCat.Meow(); rather than having to say var newCat = (Cat)(someCat.Clone()); newCat.Meow();. Unfortunately, there would be no way to have a type SiameseCat properly derives from Cat, since the only way to have mySiameseCat.Clone(); return a SiameseCat would be to have SiameseCat derive from AnimalBase<SiameseCat>, but that would prevent it from deriving from Cat.
If rather than having a class constrain to its own type, one instead defines a generic interface and constrains to that, one may avoid such difficulties. There would be no problem having SiameseCat derive from Cat while implementing IAnimal<SiameseCat>. Further, interfaces are covariant, so a type which implements IAnimal<SiameseCat> could implicitly also implement IAnimal<Cat> [if Cat was an abstract type that didn't implement the interface itself]. Every derivative of the class would have to provide its own implementations of any methods whose return value varies with the generic type parameter, but from the caller's perspective, the interface types could behave perfectly with derived classes.
It looks to be guaranteeing the type is two-dimensional (if that term makes sense here).
For example: Node<int> would end up being Node<Node<int>>.

Ensuring a generic collection contains objects that derive from two base objects

I have an interesting problem that I keep circling around, but I never seem to quiet find a solution.
I tend to be a defensive programmer, so I try to write code that prevents problems from happening rather than reacting to problems once they've occurred. To that end, I have the following situation. Take the following code:
public class Base {}
public Interface IBase {}
public class Derived : Base, IBase {}
public class Derived2 : Base, IBase {}
...
public class DerivedN : Base, IBase {}
public class X : Base {}
public class Y : IBase {}
I need to pass a list of objects that derive from Base and implement IBase to a collection, and I need to make sure that only objects that have both are added to the list. Additionally, there can be an arbitrary number of classes that have both, so I cannot use the derived classes as constraints.
If I make the list of type Base, then I could add a Y object. If I make it of type IBase, then objects of type X can be added (neither of which are permitted).
I could, of course create my own generic collection class that has both types and has constraints for both. But, I don't want to have to do this for all possible collection types, and it's a lot of effort to duplicate all that functionality (even if you just forward the method calls to a contained class).
I could also create a BaseWithIBase class, which derives from both Base and IBase, and use that as my collection type, but I really don't want to force another abstraction if I don't have to.
I don't want this to be a runtime check, so walking the tree and throwing exceptions is not acceptable.
Can anyone suggest a better approach to this problem?
NOTE: Base and IBase are not related, just pointing out they are both base items of different types.
EDIT:
It seems that everyone wants to insist that "you don't need to do that" and that it's "not OOP". Nothing could be further from the truth. I was attempting to remove the specific from the question to prevent these kinds of questions and comments, so I will include my real situation.
The code is an implement of a Windows Service framework, based on the .NET Frameworks ServiceProcess.ServiceBase class. I am adding my own framework on top of this, that is intended to be heavily Dependency Injection based, and highly testable.
The collection must contain objects that derive from both ServiceBase and IService. IService is my framework extension that is used in my code, and for testing. It is basically just this:
public interface IService
{
void Start();
void Stop();
}
In addition, I have a number of other interfaces:
public interface IRestartableService
{
void Restart();
}
public interface IConfigurableService
{
void Configure();
}
etc.. etc.. and a service may look like this:
public class MyService : ServiceBase, IService, IConfigurableService {}
My code requires IService, Windows requires ServiceBase, thus both are needed because I work with IService, and windows works with ServiceBase. I only require IService, the other interfaces are optional.
You can create your own wrapper collection simply:
// TODO: Work out which collection interfaces you want to implement
public class BaseList
{
// Or use List<IBase>, if that's how you'll be using it more often.
private List<Base> list = new List<Base>();
public void Add<T>(T item) where T : Base, IBase
{
list.Add(item);
}
}
By using a generic method with both constraints, you can be sure that Add can only be called with an appropriate type argument.
You could have two methods to expose the data as IEnumerable<T> - one returning IEnumerable<IBase> (using Cast<T>) and one returning IEnumerable<Base>... that would let you use LINQ on either type, but not both at the same time of course.
I suspect you may find this awkward elsewhere, however - you may find yourself littering your code with generic methods which you wouldn't typically need. While there may well be a good reason for wanting both the class part and the interface part, it would be worth taking a step back and considering whether they're really both necessary. Is there something extra you could add to the interface so that you could do away with the class constraint, for example?
There is no good answer to your question because the design itself is not really fitting OOP as implemented in C#/.NET.
If you absolutely need a collection where each element statically provides two independent interfaces, either a wrapper collection or some wrapper class like Wrapper<TFirst, TSecond, T> : IBoth<TFirst, TSecond> would solve your problem.
Example:
public interface IBoth<TFirst, TSecond> {
TFirst AsFirst();
TSecond AsSecond();
}
public class Wrapper<T, TFirst, TSecond> : IBoth<TFirst, TSecond>
where T : TFirst, TSecond
{
private readonly T _value;
public Wrapper(T value) {
_value = value;
}
public TFirst AsFirst() {
return _value;
}
public TSecond AsSecond() {
return _value;
}
}
However the real question is why do you need that. Not to say that standard OOP model is perfect, but quite often a problem can be solved much easier if original design decisions are reviewed.
Another option is to completely ignore ServiceBase in most of the code and create a ServiceBaseAdapter for communication with the code that is not interface friendly. Such adapter can just call your interface methods when its method are called.
Try something like this:
List<object> collection = new List<object>();
foreach(var obj in collection.OfType<Base>().OfType<IBase>())
{
// Do what ever you want
}

Error implementing Generic Class with Type Constraints

I have a Generic Base Class that I want to allow one of two types ITest or IBoldface.
My Base Class looks like this:
public abstract class BaseTestingCollections<T> where T : ITest, IBoldface
{
...
}
One of the classes that inherit it looks like this:
public class TestCollection : BaseTestingCollections<ITest>, ITestCollection
{
...
}
When I compile I get this error:
The type DomainLogic.ITest' cannot be used as type parameter 'T' in the generic type or method 'DomainLogic.BaseTestingCollections'. There is no implicit reference conversion from 'DomainLogic.ITest' to 'DomainLogic.IBoldface'.
Such an either/or restriction can't be done (as I'm sure you've noticed, the comma is more like && than ||). You can either make two different abstract classes with different names (one BaseTestingCollectionsTest<T> where T : ITest, the other BaseTestingCollectionsBoldface<T> where T : IBoldface), or remove the static restriction and put the check at runtime. Or make one of ITest or IBoldface extend the other, or extend a common interface, if they share members.
Here's an example of checking at runtime:
public abstract class BaseTestingCollections<T>
{
public BaseTestingCollections()
{
if (!typeof(ITest).IsAssignableFrom(typeof(T)) && !typeof(IBoldface).IsAssignableFrom(typeof(T)))
throw new Exception();
}
}
Well you're not satistfying the constraint you've specified. T has to extend/implement both ITest and IBoldFace.
Your constraint doesn't mean that it has to extend/implement one of the types - it has to do both. A type argument has to satisfy all the type constraints in order to be valid.
See MSDN on generic constraints for more information.
Per your own generic constraint, only those types which implement both ITest and IBoldface are suitable generic arguments for your BaseTestingCollection class.
It's not either-or, how could it be? What happens when you call method Bar from the ITest interface on a T which only implements IBoldFace, which in turn defines no method Bar? What is a compiler to do when faced with such a scenario?
There is no reasonable action to take. Your constraints apply all at the same time to the generic argument.
You can't express an "either-or" constraint like this with C# generics. Use a common base interface of some sort:
interface ITestOrBold {}
interface ITest : ITestOrBold {}
interface IBoldface : ITestOrBold {}
class BaseTestingCollections<T> where T : ITestOrBold {}
Obviously instead of ITestOrBold you should have some sensible abstraction.

c# generics on a method with the constraint that the type must be of "this" type

I have a C# class hierarchy with a common base type and two derived types. I want to declare an abstract method on the base class something like this :
public abstract IEnumerable<T> GetSiblings<T>() where T : MyBaseClass
... and I want this method to be implemented in the derived classes such that T is the type of that derived type, for each of the derived types, ie, in derived class A:
public override IEnumerable<A> GetSiblings<A>() { ... }
... and in derived class B ...
public override IEnumerable<B> GetSiblings<B>() { ... }
Put another way, each derived class must implement the method so that it returns an IEnumerable of items of the same type. Is there any way to implement this in C# ?
Well, you can hardly call a method generic if it only accepts a parameter of a single type, and your method signatures will have different return types which isn't allowed. Why don't you define an interface for all of these classes and simply return an IEnumerable<IMyClass>?
You can't do this because the return types are different. Simple as that. The reason is if you create an instance of A and stuff it into your base class(cast it) then the return type will be wrong.
You might be able to to use new instead but that might break your hierarchy.
This is not supported by the type system. It's a common enough problem, represented often as
class Animal<T> where T : Animal<T> { }
class Cat : Animal<Cat> { } // what you desire
class Dog : Animal<Cat> { } // what is possible yet not desired
But not a problem that has as yet been acted upon by the appropriate parties (be it the framework providers or C# team, not sure who).
Until it passes the critical "worth it" test as determined by costs (and opportunity costs) versus benefits, you'll have to work around it.
I found the solution. Apparently in C# 4.0, generic parameter types can be covariant, so what I've posted above will work. C# 3.5 or lower, and it doesn't work. Took a lot of Googling.

Categories

Resources