I have a basic structure of generic's classes
public class Parent<T> where T : Parent<T>
{
Action<T> Notify;
}
public class Child : Parent<Child>
{
}
And I want to have a list so that Child objects can be put there
List<Parent> parents = new List<Parent>();
In java I just can write List<? extends Parent> and all Parent's subclasses easily can be added to the list. Is there any alternative of this in C#?
You can't do the same thing as Java, because in Java, generics use type erasure and break variance. Essentially, your Java code turns everything into List<object>, and hopes for the best. The only reason why List<?> is better than List<Object> is that not everything is an Object in Java - in C#, you can put an integer inside a List<object> just fine. Mind, a List<int> will perform much better than List<object>, if you can afford it - that's one of the big reasons why generics were originally added to C#.
C# is a bit stricter than that. You can't do anything like new List<Parent<T>>() that would allow any kind of Parent<T>. If you had more limited requirements, you could use a variant interface instead, but that wouldn't work with List<T> for obvious reasons.
Your only real option is to make the base class non-generic. The user of your list can't know anything about the T in advance anyway, so any part of the Parent interface that returns or takes T wouldn't be useful without casting anyway (Java does the casting for you, but it's still casting - neither Java's nor C#'s generics are powerful enough for what you're trying to do).
public abstract class Parent
{
// The common methods
public abstract int Id { get; }
}
public abstract class Parent<TChild> : Parent, IEnumerable<TChild>
{
// The methods that are TChild-specific - if you don't need any of those, just drop
// this class, the non-generic one will work fine
private List<TChild> children;
public void Add(TChild child) => ...
public TChild this[int index] => ...
}
public class Child : Parent<TChild>
{
...
}
Now to get a list of all possible children, you can use
var list = new List<Parent>();
And when you need to get e.g. all the Child items, you can do
var children = list.OfType<Child>();
Just for completeness sake, you can get similar behavior to Java's with C#'s dynamic. But I'm not even going to show any sample of that - dynamic is a useful tool, but mainly for more dynamic typing problems. It's overkill for something as simple as this, and trades compile-time issues for run-time issues.
In general, if you ever use Parent<T> directly, it should be in a generic method - e.g. an extension method that has some common functionality for all Parent<T>s. You can't instantiate a generic type that doesn't have all the type arguments known at the time in C#.
Declaration List<Parent> parent; does not compile, since it requires type argument.
And when you say, public class Child : Parent<Child> it inherits Parent<Child> and not Parent<T>
So List<Parent<Child>> list; will only accept objects of Child class, and not of any other subclass of Parent.
Still you can achieve what you need with help of an interface as below: working fiddle here
public class Program
{
public static void Main()
{
List<Parent<IParent>> parentList = new List<Parent<IParent>>();
parentList.Add(new Child1());
parentList.Add(new Child2());
}
}
public class Parent<T>
{ }
public interface IParent
{ }
public class Child1 : Parent<IParent>, IParent
{ }
public class Child2 : Parent<IParent>, IParent
{ }
Related
Yesterday, I was explaining C#'s generic constraints to my friends. When demonstrating the where T : CLASSNAME constraint, I whipped up something like this:
public class UnusableClass<T> where T : UnusableClass<T>
{
public static int method(T input){
return 0;
}
}
And was really surprised to see it compile. After a bit of thinking, however, I figured it was perfectly legal from the point of view of the compiler - UnusableClass<T> is as much of a class as any other that can be used in this constraint.
However, that leaves a couple of questions: how can this class ever be used? Is it possible to
Instantiate it?
Inherit from it?
Call its static method int method?
And, if yes, how?
If any of these is possible, what would the type of T be?
This approach is widely used in Trees and other Graph-like structures. Here you say to compiler, that T has API of UnusableClass. That said, you can implement TreeNode as follows:
public class TreeNode<T>
where T:TreeNode<T>
{
public T This { get { return this as T;} }
public T Parent { get; set; }
public List<T> Childrens { get; set; }
public virtual void AddChild(T child)
{
Childrens.Add(child);
child.Parent = This;
}
public virtual void SetParent(T parent)
{
parent.Childrens.Add(This);
Parent = parent;
}
}
And then use it like this:
public class BinaryTree:TreeNode<BinaryTree>
{
}
Well.
public class Implementation : UnusableClass<Implementation>
{
}
is perfectly valid, and as such makes
var unusable = new UnusableClass<Implementation>();
and
UnusableClass<Implementation>.method(new Implementation());
valid.
So, yes, it can be instantiated by supplying an inheriting type as the type parameter, and similarly with the call to the static method. It's for instance useful for tree-like structures where you want to generically specify the type of children the node has, while it being the same type itself.
If any of these is possible, what would the type of T be?
They are all possible, and you are the one who is gonna determine what is the type of T.For example let's assume there is a type that inherits from UnusableClass<T>
class Foo : UnusableClass<Foo> { }
Now you can instantiate UnusableClass<Foo> because Foo satisfies the constraint:
UnusableClass<Foo> f = new UnusableClass<Foo>();
Then the type of T become Foo and if you try to call method you need to pass an instance of Foo.
I currently have a small object hierarchy that looks like this:
public class BaseClass {
// this class is empty and exists only so the others can extend it and share the
// same base type
}
public class ChildA : BaseClass {
public Subject<AssociatedClassA> Results;
}
public class ChildB : BaseClass {
public Subject<AssociatedClassB> Results;
}
In my design I would like to enforce that every class that extends from BaseClass should contain a Subject<SomeType> called Results. I'm wondering if there is a way that I can move Results into the base class or an interface such that I can supply the generic type for the Subject when constructing the base class. For example, it would be awesome if I could do something like this:
ChildA<AssociatedClassA> instance = new ChildA<AssociatedClassA>();
Or even better since there should really only be one template parameter that matches with ChildA if when I constructed it that could be taken care of for me:
ChildA instance = new ChildA();
// Results is automatically set to Subject<AssociatedClassA>
I'm stuck trying to implement this now as if I try to move Results into the base class the Subject requires a template parameter which I can't necessarily supply. There could potentially be more than 2 derived classes and I don't like the idea that someone extending this system has to know to add Results manually to each child class.
Following the suggestions of the 2 answers below this solves my desire to move Results into the base class, however I've run into another issue in that I was hoping to be able to use BaseClass as a generic parameter to methods such that any of the derived classes could be used. For example:
public void ProcessBaseClass(BaseClass base) {
// base could be ChildA or ChildB here
}
This no longer works since BaseClass now requires a type argument. Is there any way that I can have the best of both worlds here or am I stuck due to my design choices?
If appropriate, you can make the parent generic:
public class BaseClass<T> {
public Subject<T> Results;
}
public class ChildA : BaseClass<AssociatedClassA> {
}
public class ChildB : BaseClass<AssociatedClassB> {
}
You can make the base class itself generic:
public class BaseClass<T> {
public T Results { get; protected set; }
}
imagine this layout of classes i use for building a tree structure:
class Treenodebase
{
Treenodebase Parent{get;set;}
IEnumerable<Treenodebase> Children {get;set;}
}
class Specialtreenode : Treenodebase
{
string SpecialProperty{get;set;}
public string ParentsSpecialProperty()
{
return Parent.SpecialProperty; //here I'd need casting?!
}
}
class Othertreenode : Treenodebase
{
string OtherProperty {get;set;}
}
I use the subclasses to build seperate trees throughout my program. that means each Specialtreenode only ever has a parent of type Specialtreenode, and also children of type Specialtreenode.
The snipped is very simplified. The base class has many more properties (like IsSelected and IsExpanded) and methods (think 'Ancestors' or 'Siblings' and the like) and the subclasses too.
Can I somehow utilize type parameters here to avoid casting within each of the subclasses? Or would that always involve my subclasses not inheriting from the baseclass?
You could do something like this:
class Treenodebase<T> where T : Treenodebase<T>
{
public T Parent{get;set;}
public IEnumerable<T> Children {get;set;}
}
class Specialtreenode : Treenodebase<Specialtreenode>
{
string SpecialProperty{get;set;}
public string ParentsSpecialProperty()
{
return Parent.SpecialProperty;
}
}
Of course, this eliminates the non-generic Treenodebase type, which could be good or bad. If you have a lot of utility methods that don't really care what implementation you use, you might want to make Treenodebase<T> either extend a non-generic base class or implement a non-generic interface. On the other hand, you might find it easier to just make all your utility methods be generically typed as well. It depends on how you're using the tree in code.
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.
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 )