How can a class inherit from a parameterized version of itself? - c#

I saw a C# class SomeClass that was defined like
public class SomeClass : IComparable<SomeClass>, IEquatable<SomeClass>
{
// ...
}
and I'm wondering how to translate that into English. The way I understand it seems logically impossible. How can a class inherit from a parameterized version of itself? Also, is this a common design pattern?

The key is to recognize that it's not inheriting from (or implementing) a parameterized version of itself, but rather inheriting from (or implementing) another class or interface, and using itself as a generic parameter for that target type.
For example, IComparable<T> says that there will be a CompareTo() method that takes an object of type T as a parameter. So by implementing IComparable<SomeClass> you're simply guaranteeing that a method with that signature will exist on this class:
public class SomeClass : IComparable<SomeClass>
{
public int CompareTo(SomeClass other)
{
//...
}
}
And yes, this is fairly common practice. Classes often implement the generic IComparable<> and IEquatable<> interfaces to show that they can be compared with other items of the same type. It's maybe also worth mentioning that enums in Java are declared as extending Enum<> of themselves--a pattern which is not common in C#, but does appear from time to time.

Translated in "English" it means: "Boy (or girl), you'd better be type-safe when implementing those interfaces, especially IComparable. Otherwise, you'll have to perform type casting, which I guess you don't want"
See the code below. SomeClass implemented IComparable and IComparable.
See differencies between implementations of CompareTo(object) and CompareTo(SomeClass).
namespace InterfacesStuff
{
internal class Program
{
private static void Main(string[] args)
{
var someClass1 = new SomeClass {ComparedValue = 1};
var someClass2 = new SomeClass {ComparedValue = 2};
//someClassObject defined as SomeClass
//object someClassObject = new SomeClass { ComparedValue = 2 };
//someClassObject defined as anything else but SomeClass
object someClassObject = 5;
int comparisonSomeClassBySomeClass = someClass1.CompareTo(someClass2);
int comparisonSomeClassByObject = someClass1.CompareTo(someClassObject);
}
}
public class SomeClass : IComparable, IComparable<SomeClass>, IEquatable<string>, IEquatable<int>,
IEquatable<double>
{
public int ComparedValue;
public int CompareTo(object obj)
{
var presumedSomeClassObject = obj as SomeClass;
if (presumedSomeClassObject != null)
{
if (ComparedValue <= ((SomeClass) obj).ComparedValue)
return -1;
}
return 0;
}
public int CompareTo(SomeClass other)
{
if (ComparedValue <= other.ComparedValue)
return -1;
return 0;
}
public bool Equals(double other)
{
throw new NotImplementedException();
}
public bool Equals(int other)
{
throw new NotImplementedException();
}
public bool Equals(string other)
{
throw new NotImplementedException();
}
}
}

It is not Inheriting, It is implementing the IComparable Interface. what is going on is
Someclass Implements the Icomparable and the IEquatable interface. Implementing an interface is like signing a contract stating you gaurentee that this class will implement the methods on an interface.
Icomparable msdn, IEquatable. If you look at the MSDN pages you can see that SomeClass gaurentees it will implement the methods in some fashion.
This is very common practice and it is many different names. The ones I hear most are programming by contract and Implementation over Inhertience. It lets you do a lot of cool things, like Dependency Injection, Proper Unit testing, better Generics. It does this because the compiler doesnt need to know the concrete class that your object is implementing. It just needs to know that it has certain functions on it. For further reading on this I would read Chapter one of the gang of four Design pattern book.
Wikipedia link Specifically the Introduction to Chapter one section

It doesn't really have to be convenient to express it in english for it to be valid code, although I'd probably read that as "SomeClass is comparable and equatable to itself". That doesn't really explain what's going on though, it's just a way of expressing it.
In C# types can be generic over categories of other types. Generic types are basically "type constructors". They take other types as parameters, and use them to construct new types. For instance, IEnumerable<int> and IEnumerable<string> are two completely different types. The non-generic version (IEnumerable) is a third one. In C# a type A can inherit ANY other type B as long as none of the following is true (I hope I didn't miss anything):
B is already a subtype of A
B is a class and A has already inherited another class
B is a struct
A is an interface but B is not
A is the same type as B
B is sealed
A is a struct and B is not an interface
This even makes the following code legal:
class Foo<T>
{
public T Value;
}
class Foo : Foo<int>
{
}
Foo and Foo<T> are different types, so there's no problem at all for one to inherit the other.
You can read more about generics here:
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
And about inheritance here:
https://msdn.microsoft.com/en-us/library/ms173149.aspx

The code you posted does not inherit from any class. It is implementing certain so-called Interfaces. How to translate that snippet: "I guarantee that SomeClass will be Comparable and equatable with other SomeClass instances. I will provide definitions in this class on how to do that."
About specializing a class from some other class...
What you can do is something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Pet
{
protected string name;
public Pet(String name)
{
this.name = name;
}
}
class Dog : Pet
{
private List<String> tricks;
public Dog(String name, List<String> tricks):base(name)
{
this.tricks = tricks;
}
}
class Program
{
static void Main(string[] args)
{
List<string> tricks = new List<string>();
tricks.Add("sit");
tricks.Add("jump");
tricks.Add("bark");
Dog puppy = new Dog("Fido", tricks);
}
}
}
Dog inherits from Pet. Dog calls Pet's constructor at creation. Whatever name you pass into Dog constructor, it will forward it to Pet constructor.
Because what happens is that a subclass first calls the constructor of its superclass with the appropriate arguments. Then it runs its own constructor. Whatever is declared as public or protected in a class will be visible to its subclasses.
Therefore Dog will have name and also a list of tricks:
You achieve this kind of view with the "Locals" window.
I recommend that you read some tutorials on c# inheritance, interfaces and generics

Related

Generic method with type constraints or base class parameter

If I write a method accepting a parameter which derives from a BaseClass (or an interface), as far as I know there are two ways to achieve that:
void MyMethod<T>(T obj) where T : BaseClass { ... }
and
void MyMethod(BaseClass obj) { ... }
What are the differences between the two methods?
In this example there isn't a big difference between the two, you can access the same members inside the method and you can call it with the same derived classes. There is a runtime difference as a generic method is compiled for each type it is invoked with.
Where generics come in useful would be if you would return a value depending on T
With generics you could do the following
T MyMethod<T>(T obj) where T : BaseClass { ... }
MyMethod(derivedInstance).derivedProperty
Without this would be an error:
BaseClass MyMethod(BaseClass obj) { ... }
MyMethod(derivedInstance).derivedProperty // error
Note Although you mention constraining to a base class, it is worth mentioning that if you constrain not to a class, but to an interface, extra boxing will occur if the implementation is by a struct in the non generic version, this can have severe performance implications.
When T is constrained to a base class, there is not really much difference apart from what has already been stated.
When T is constrained to an interface, the difference can be huge:
int FrobNonGeneric(IFrobbable frob) { //... }
int Frob<T>(T frob) where T: IFrobbable { //... }
struct Frob: IFrobbable { ... }
FrobNonGeneric(new Frob()); //boxing!
Frob(new Frob()); //no boxing
Definitely the example you quoted does not make much difference other than run time execution performance as mentioned in other answers.
Leaving aside generic collections benefits (performance improvement by avoiding boxing/unboxing for example) which we all aware of and we use frequently - Generics also works great from a consumer perspective. For example, the below code snippet is self explanatory to visualize API usage flexibility from a consumer perspective :
interface IEntity
{
int Id {get;set;}
}
class Student : IEntity
{
int Id {get;set;}
string SubjectOpted {get;set;}
}
class Employee : IEntity
{
int Id {get;set;}
string DepartmentName{get;set;}
}
interface INonGenericRepository
{
IEntity Get(int id)
}
interface IGenericRepository<T> where T:Entity
{
T Get(int id)
}
class NonGenericRepository : IRepository
{
public IEntity Get(int id) {/*implementation goes here */
}
class GenericRepository<T> : IRepository<T>
{
public T Get(int id) {/*implementation goes here */
}
Class NonGenericStudentConsumer
{
IEntity student = new NonGenericFRepository().Get(5);
var Id = student.Id
var subject = student.SubjectOpted /*does not work, you need to cast */
}
Class GenericStudentConsumer
{
var student = new GenericFRepository<Student>().Get(5);
var Id = student.Id
var subject = student.SubjectOpted /*works perfect and clean */
}
A couple of other use cases promoting flexibility while using generics along with constraints are :
Lets say I want to ensure parameter passed to method implements IAdd and IMultiply and I have class which implements both IAdd,IMulitply like :
public class BusinessOpeartion<T> where T : IAdd, IMultiply{
void SomeBusinessOpeartion(T obj) { /*implementation */}
}
If I need to go via non generic approach, I am forced to create redundant dummy interface like :
interface IDummy : IAdd, IMultiply
public class BusinessOpeartion{
void SomeBusinessOpeartion(IDummy obj) { /*implementation */}
}
Isn't the former approach cleaner?
Also one more small thing just popped up while typing answer. In case you need to, how would you get new instance for parameter type inside method:
you cannot do
IDummy dummy = new IDummy(); /*illegal*/
But with generic you could have; T temp = new T(); provided there is constraint of new()
Also what if you need a default value for parameter type?
you cannot do
var default = default(IDummy); /*illegal*/
But with generic you could have; var default = default(T)
As was said, it matters only once you get a return value. Consider these cases:
BaseClass MyMethod(BaseClass)
DervivedClass temp = new DervivedClass();
//Error. My Method always returns a BaseClass. No implicit casting available
temp = MyMethod(temp);
Compare it to this:
T MyMethod<T>(T) where T : BaseClass
DervivedClass temp = new DerivedClass();
temp = MyMethod<DerivedClass>(temp);
Strong Typification is one of the best friends you have in .NET. Embrace it. Never try to avoid it. The opposite would be cases like we have in PHP and JavaScript: http://www.sandraandwoo.com/2015/12/24/0747-melodys-guide-to-programming-languages/
In the examples included in your question, there isn't much difference between the generic and the non-generic version. But here are some other examples of method signatures that can't be expressed without generics:
T MyMethod<T>(T obj) where T : BaseClass { ... }
void MyMethod<T>(T obj1, T obj2) where T : BaseClass { ... }
void MyMethod<T>(T obj, List<T> list) where T : BaseClass { ... }

Overriding (shadowing, overloading?) methods with different return types in a C# hierarchy

I'm writing an SDK which has an OOP structure for implementing data types;
first an interface
then an abstract implementation
finally an abstract generic implementation
People can choose to implement either the interface, or derive from either of the classes.
public interface IGoo
{
IGoo Duplicate();
...
}
public abstract class Goo : IGoo
{
IGoo IGoo.Duplicate() {
return Duplicate();
}
abstract public Goo Duplicate();
...
}
public abstract class Goo<T> : Goo
{
abstract public Goo<T> Duplicate(); ??????
...
}
I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.
Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?
What about the following?
public interface IObj
{
IObj Duplicate();
}
public abstract class Obj : IObj
{
public Obj()
{
}
public virtual IObj Duplicate()
{
return this;
}
}
public abstract class ObjT<T> : Obj
{
public ObjT()
{
}
public override IObj Duplicate()
{
return this;
}
}
public class ObjImpl : Obj
{
}
public class ObjTImpl : ObjT<int>
{
}
I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
ObjImpl a = new ObjImpl();
ObjTImpl b = new ObjTImpl();
Console.WriteLine(a.Duplicate().GetType());
Console.WriteLine(b.Duplicate().GetType());
Console.ReadLine();
}
}
}
// outputs:
// ObjImpl
// ObjTImpl
The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.
Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.
There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol
It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.

Generic List of Generic Interfaces not allowed, any alternative approaches?

I am trying to find the right way to use a Generic List of Generic Interfaces as a variable.
Here is an example. It is probably not the best, but hopefully you will get the point:
public interface IPrimitive<T>
{
T Value { get; }
}
and then in another class, I want to be able to declare a variable that holds a list of objects that implement IPrimitive<T> for arbitrary T.
// I know this line will not compile because I do not define T
List<IPrimitive<T>> primitives = new List<IPrimitives<T>>;
primitives.Add(new Star()); // Assuming Star implements IPrimitive<X>
primitives.Add(new Sun()); // Assuming Sun implements IPrimitive<Y>
Note that the T in IPrimitive<T> could be different for each entry in the list.
Any ideas on how I could setup such a relationship? Alternative Approaches?
public interface IPrimitive
{
}
public interface IPrimitive<T> : IPrimitive
{
T Value { get; }
}
public class Star : IPrimitive<T> //must declare T here
{
}
Then you should be able to have
List<IPrimitive> primitives = new List<IPrimitive>;
primitives.Add(new Star()); // Assuming Star implements IPrimitive
primitives.Add(new Sun()); // Assuming Sun implements IPrimitive
John is correct.
Might I also suggest (if you are using C# 4) that you make your interface covariant?
public interface IPrimitive<out T>
{
T Value { get; }
}
This could save you some trouble later when you need to get things out of the list.
You say it won't work because you don't define T. So define it:
public class Holder<T>
{
public List<IPrimitive<T>> Primitives {get;set;}
}
This is one of the most complicated elements of the c# language though it is incredibly important for building well defined components. As such, c# falls short. However it is definitely possible to make this work.
The trick is to have 3 parts:
A non generic interface that contains all requirements of the interface.
A generic abstract class that implements the non generic interface and performs the type conversions as necessary.
A class that implements the generic abstract class with the appropriately typed results
For example:
public interface INonGenericInterface{
void Execute(object input);
object GetModel();
}
public abstract class IGenericInterfaceBase<T> : INonGenericInterface{
void INonGenericInterface.Execute(object input){
Execute((T) input);
}
object INonGenericInterface.GetModel(){
return GetModel();
}
protected abstract void Execute(T input);
protected abstract T GetModel();
}
public class ImplementingClass : IGenericInterfaceBase<ModelClass>{
protected override void Execute(ModelClass input){ /*Do something with the input */ }
protected override ModelClass GetModel(){ return new ModelClass();}
}
//Extras for demo
public class ModelClass { }
public class ModelClass2 { }
public class ImplementingClass2 : IGenericInterfaceBase<ModelClass2>
{
protected override void Execute(ModelClass2 input) { /*Do something with the input */ }
protected override ModelClass2 GetModel() { return new ModelClass2(); }
}
var agi = new INonGenericInterface[] { new ImplementingClass(), new ImplementingClass2() };
agi[0].Execute(); var model = agi[0].GetModel();
agi[1].Execute(); var model2 = agi[1].GetModel();
//Check the types of the model and model2 objects to see that they are appropriately typed.
This structure is incredibly useful when coordinating classes w/ one another because you're able to indicate that an implementing class will make use of multiple classes and have type checking validate that each class follows established type expectations. In addition, you might consider using an actual class instead of object for the non-generic class so that you can execute functions on the result of the various non-generic calls. Using this same design you can have those classes be generic classes w/ their own implementations and thus create incredibly complex applications.
To OP: Please consider changing the accepted answer to this to raise awareness of the correct approach as all previously stated answers fall short for various reasons and have probably left readers with more questions. This should handle all future questions related to generic classes in a collection.

Why use generic constraints in C#

I've read an excellent article on MSDN regarding Generics in C#.
The question that popped in my head was - why should i be using generic constraints?
For example, if I use code like this:
public class MyClass<T> where T : ISomething
{
}
can't I switch ALL references of T in this class with ISomething?
What's the benefit of using this approach?
You ask, "can't I switch ALL references of T in this class with ISomething?" So I think you mean to compare:
public class MyClass<T> where T : ISomething
{
public T MyProperty { get; set; }
}
With:
public class MyClass
{
public ISomething MyProperty { get; set; }
}
In the second example, MyProperty is only guaranteed to be an instance of ISomething. In the first example, MyProperty is whatever T is, even if that is a specific subtype of ISomething. Consider a concrete implementation of ISomething:
public class MySomething : ISomething
{
public string MyOtherProperty { get; set; }
}
Now, if we use the first, generic, example, we could have:
MyClass<MySomething> myClass = new MyClass<MySomething>();
Console.WriteLine(myClass.MyProperty.MyOtherProperty);
On the other hand, if we used the second example, we wouldn't be able to access MyOtherProperty since it's only known to be an ISomething:
MyClass myClass = new MyClass();
Console.WriteLine(myClass.MyProperty.MyOtherProperty); // Won't compile, no property "MyOtherProperty"
On a different note, the reason these type constraints are useful is that you can refer to MyProperty (type T) and access members of ISomething. In other words, if ISomething were declared like:
public interface ISomething
{
public string SomeProperty { get; set; }
}
Then you could access MyProperty.SomeProperty. If you omitted the where T : ISomething then you wouldn't be able to access SomeProperty since T would only be known to be of type object.
Type Safety. For example, suppose you're creating a container. You can pass in something to that container and retrieve it in the proper form without having to do any casts later by parameterizing the container. You're simply defining constraints on the types of things that you're willing to store in your container.
Here's an example of the difference, by just using List<>
Image list wouldn't be generic but it would just use IListElement everywhere it used the generic instead. Now Imagine you have an object that's something like this.
class Element : IListElement
{
public string Something { get; set; }
}
now I could just do list.Add(element); and there wouldn't be a difference with a real List<Element>. However when I retreive data it's a different story, if I use the list that uses IListElement then I have to cast my data back so I can get the Something out of it. Thus i'd have to do:
string s = ((Element)list[0]).Something;
while with the generic I can just do:
string s = list[0].Something;
saves a lot of trouble, ofcourse it goes a bit further than that but I think you can get the idea from this.
Well for a start, you can call methods defined in ISomething within the code for the generic method / methods on the generic class. If T was allowed to be any type then this would not be possible (although you could always do some runtime casting).
So it allows you to enforce compile-time constraints on what T can be and therefore rely on these constraints when you write the code - turning runtime errors into compile time errors.
Yes you can use ISomething in place of T , but that will manually close the generic type to an ordinary class. It wont be a generic type any more. By using T, you keep the type open to as many ISomething subtypes as you want. Code reuse without compromising type safety is the key benefit here. For example if you use a Stack of ISomethings, you can push any ISomething onto the stack but a pop has to occur with a downcast to the actual subtype of ISomething for it to be useful. Downcasting creates a potential failure point, which will not be there in a generic Stack<T> where T:ISomething
Consumer of your class gets the benefit of increased type-safety, among others.
class Widget : IPokable { }
// No generics
Widget w = (Widget)list[0]; // cast can fail
// With generics
Widget w = list[0];
Without generics, if list was containing IPokable objects, cast is still necessary.
Class you're implementing gets the benefit of using specific methods on the generic object.
class PokableList<T> where T : IPokable {
public T PokeAndGet() {
currentObj.Poke();
return currentObj;
}
}
Perhaps this simple example might help.
If I have these classes:
public class ListOfCars<T> : List<T> where T : Car { }
public abstract class Car { }
public class Porsche : Car { }
public class Bmw : Car { }
...and then if I write this code:
var porsches = new ListOfCars<Porsche>();
// OK
porsches.Add(new Porsche());
//Error - Can't add BMW's to Porsche List
porsches.Add(new Bmw());
You can see that I can't add a BMW to a Porsche list, but if I just programmed off of the base class it would be allowed.

In c#, is there way to write a generic such that Object<Child> : Object<Parent>?

Is there a way to do something like this in c#? Consider the following example and assume that Child1, Child2, Child3 are all children of Parent -
class Class1
{
SomeObject< Parent > mSomeObject;
Class1()
{
if (condition1)
mSomeObject = new SomeObject<Child1>();
else if (condition2)
mSomeObject = new SomeObject<Child2>();
else if (condition3)
mSomeObject = new SomeObject<Child3>();
}
}
The idea is that that Class1 would have SomeObject as a member, but it is uncertain until runtime what generic form of SomeObject it should take. Any help would be appreciated. Thanks!
You should use interface based inheritance. This will allow child1, child2, and child3 to be polymorphic and take on the characteristics of the parent without the need for such guard logic. With the IF tests gone your code will be more readable and easier to modify later.
Here's and example I just wrote with LINQPad to show this in action.
public interface ICar
{
bool IsAutomatic();
}
public class Silverado : ICar
{
public bool IsAutomatic()
{
return true;
}
}
public class Semi : ICar
{
public bool IsAutomatic()
{
return false;
}
}
void Main()
{
ICar car = new Silverado();
bool isAuto = car.IsAutomatic();
isAuto.Dump();
car = new Semi();
isAuto = car.IsAutomatic();
isAuto.Dump();
}
OUTPUT:
True
False
I prefer interface based inheritance as opposed to abstract classes as described by AllenG. Reasons such as multiple inheritance - a class can implement many interface but only inherit from 1 class.
Hope this helps...
You could do this. Notice the use of the out keyword here to make the type covariant.
public interface ISomeObject<out T>
{
}
However, this will somewhat restrict what you can do with T in the interface. Specifically you can only declare members where T is in the output position. In other words, it cannot be accepted as a parameter to a function.
I've never tried it, but I believe you are correct. In general if
public class Child : Parent
then any call for Parent will be satisfied by Child.
For instance:
public class Animal { //stuff }
public class Cat : Animal { // overridden stuff }
List<Animal> pets = new List<Animal>;
pets.Add(new Cat());
would work.
If you're looking for behavior, you may want to be working with Interfaces instead of class inheritance, but it would work the same way.
No, the problem you may have with your approach is that your SomeObject<Parent> will only have access to those members in your Parent class. To use anything in the appropriate Child class, you'll need to cast back to the appropriate Child.
You can do this in C# 4.0 with an interface or a delegate but not with a class. Consider changing the property to an interface type and read more about generics covariance and contravariance in C# 4.0 (for example here: http://msdn.microsoft.com/en-us/library/ee207183.aspx )

Categories

Resources