I am new to C#. So please bear with me. I ran into a problem when I tried to compare two lists of different derived objects. I have a base class and a child class that inherits from it. The derived class has additional properties in the Equals() value comparison. I implement the IEquatable<> interface in the bass class as well as the derived class. I then fill two lists, each with one object from the derived class. The problem is when I call the Equals() function, it is the Base.Equals() that gets called. So basically the items in the list are treated as base class objects instead of the derived objects. How do I get out of this? See below code:
public class Base : IEquatable<Base>
{
...
public int BaseProperty {get; set;}
...
public virtual bool Equals(Base other)
{
...
return this.BaseProperty == other.BaseProperty;
}
}
public class Derived : Base, IEquatable<Derived>
{
public int DerivedProperty {get; set:}
...
}
public class myList : IList<Base>, IEquatable<myList>
{
private List<Base> _list;
...
public bool Equals(myList other)
{
...
return ENumerable.SequenceEqual(this._list.OrderBy(r => r), other._list.OrderBy(r = > r));
}
}
Main()
{
Derived first = new Derived() {...};
Derived second = new Derived() {...};
myList<Derived> list1 = new List<Derived>(){ first };
myList<Derived> list2 = new List<Derived>(){ second };
bool ret = list1.Equals(list2);
}
The comparison of the two lists is done using SequenceEqual. When I stepped into the calls, I could see the trace ended up in Base.Equals(Base other) instead of Derived.Equals(Derived other). I can't cast it because in reality I have multiple derived classes and the lists could potentially hold any numbers of any objects. So my question is is there a way to make C# respect the derived type(s) in this situation? Thanks.
To try and answer your ultimate question -
So my question is is there a way to make C# respect the derived type(s) in this situation? Thanks.
The reason that the Base.Equals method (rather than the Derived.Equals method) is called is because of your declaration of 'myList' actually defines the Base class -
public class myList : IList<Base>, IEquatable<myList>
Instead, if you implement the myList in a generic way, then there will be no implicit conversion to Base when creating a myList object using the Derived class -
public class myListGeneric<T> : IList<T>, IEquatable<myListGeneric<T>> where T : class
I have tried as best as I can to implement an example for you on the following link (albeit inheriting from generics rather than their interfaces) to try and show you it working. It does differ slightly from what you have above, but it hopefully answers the question.
https://dotnetfiddle.net/VhWTCq
Hope that helps - copy it, step through, and have a go.
Related
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
{ }
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
I have a simple class structure
abstract class A {
List<A> containerList;
...
}
class B : A {....}
class C : A {....}
I make sure that the containerList contains only elements of class B or C (as the list is filled in these child classes and A is abstract).
Now, I'd like, somehow, to have a base property / method in A which would cast itself to whatever the real type of the object is, i.e. B or C. Having an abstract method is just fine, but it is important to get a Collection<T> of B or C objects, as I have bindings that will depend on it.
Now, I'd like, somehow, to have a base property / method in A which would cast itself to whatever the real type of the object is, i.e. B or C.
I think you're mixing casting and converting. A Cast is a compile-time construct that just determines how methods and properties are bound at compile-time. It does not change the underlying object.
There's no conversion necessary because the object is already either a B or a C - since A is abstract you can't have an object that is actually an A.
So a method that returns the underlying collection as either a collection of Bs or Cs would just be:
public IEnumerable<B> GetBs()
{
return containerList.OfType<B>();
}
public IEnumerable<C> GetCs()
{
return containerList.OfType<C>();
}
If you want one generic method where the caller determines the type, you can do:
public IEnumerable<T> GetTs<T>() where T:A
{
return containerList.OfType<T>();
}
You could use generics like that (though it looks a little strange):
public abstract class A<T> where T : A<T>
{
protected List<A<T>> containerList;
public Collection<T> ContainerList
{
get { return new Collection<T>(containerList.OfType<T>().ToList()); }
}
}
public class B : A<B>
{
//...
}
public class C : A<C>
{
//...
}
But since containerList should only contain elements of the derived type, you can make it completely generic too like that:
protected List<T> containerList;
and could ommit the OfType() call:
public Collection<T> ContainerList { get { return new Collection<T>(containerList); }}
One drawback is that someone could have the idea to make a class D like that:
public class D : A<B>
{}
and would now have a class D with a ContainerList of type Collection<B>. But if it's that what he wants...
Instead of casting the objects in the list, you could use the is keyword (documentation link). When you need to operate on your List, just ask before doing your operation if (containerList[i] is B).
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.
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 )