C# covariance structure understanding? - c#

Assuming
class A
{ }
class B : A
{ }
covariance is not supported for generic class.
Meaning - we cant do something like this :
MyConverter<B> x1= new MyConverter<B>();
MyConverter<A> x2= x1;
Thats fine and understood.
From my reading - i understand that Covariance will be available:
"If you use a backing Generic Interface Being implemented on a Generic Class - so that access to the T type object instance will be available through those interfaces ".
I have just one problem.
Ive seen many examples of the "converter" class as a form of Stack .
But never understood " what if I want to use only 1 instance of B from a reference of A ? "
so Ive tried some code :
Create B object + values ---> use Generic Converter for B --->
use the covariance flow to get its A reference ---> now you can use it
either as A or as B.
My question :
Is That the correct way of doing this ( for using covariance for 1 object only ) ?
p.s.
The code is working and compiled ok. http://i.stack.imgur.com/PJ6QO.png
Ive been asking /reading a lot about this topic lately - I dive into things in order to understand them the best I can.

Your code compiles and works, so is it "correct"? I guess it is!
However it is not very interesting having a stack that only contains a single element; that's not really a stack. Let's think about how you might make a truly covariant and contravariant stack.
interface IPush<in T> { void Push(T item); }
interface IPop<out T> { T Pop(); }
class Stack<T> : IPush<T>, IPop<T>
{
private class Link
{
public T Item { get; private set; }
public Link Next { get; private set; }
public Link(T item, Link next) { this.Item = item; this.Next = next; }
}
private Link head;
public Stack() { this.head = null; }
public void Push(T item)
{
this.head = new Link(item, this.head);
}
public T Pop()
{
if (this.head == null) throw new InvalidOperationException();
T value = this.head.Item;
this.head = this.head.Next;
return value;
}
}
And now you can use the stack covariantly for popping, and contravariantly for pushing:
Stack<Mammal> mammals = new Stack<Mammal>();
IPop<Animal> animals = mammals;
IPush<Giraffe> giraffes = mammals;
IPush<Tiger> tigers = mammals;
giraffes.Push(new Giraffe());
tigers.Push(new Tiger());
System.Console.WriteLine(animals.Pop()); // Tiger
System.Console.WriteLine(animals.Pop()); // Giraffe
What if I want to use only one instance of B from a reference of A?
Your question is "what if I want to use a Tiger but I have a reference an Animal?" The answer is "you can't" because the Animal might not be a Tiger! If you want to test whether the reference to Animal is really a tiger then say:
Tiger tiger = myAnimal as Tiger;
if (tiger != null) ...
or
if (myAnimal is Tiger) ...
What about if you want to convert class C<B> to C<A>?
That's not possible. There is no reference conversion there. The only covariant and contravariant reference conversions in C# 4 are on generic interfaces and generic delegates that are constructed with reference types as the type arguments. Generic classes and structs may not be used covariantly or contravariantly. The best thing you can do is make the class implement a variant interface.

It looks like you're using the converter simply to get a reference of type A pointing to an object of type B. There's a much easier way to do that, called casting:
B b = new B();
A a = (A)b;
In fact, since A is a superclass of B, the conversion is implicit:
B b = new B();
A a = b;
Your program could be:
class Program
{
static void Main(string[] args)
{
B b = new B { b1 = 22222 };
A a = b;
Console.WriteLine(a.a1);
Console.WriteLine(((B)a).b1);
}
}

IPushable<B> x1 = new MyConverter<B>();
x1.Set(b);
// I believe this is valid.
IPoppable<A> final = x2;
You can find some great examples and descriptions of it on this blog.

Related

How to cast generic type T to interface? [duplicate]

Is there a way to test if T inherits/implements a class/interface?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
There is a Method called Type.IsAssignableFrom().
To check if T inherits/implements Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
If you are targeting .NET Core, the method has moved to TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())
Note that if you want to constrain your type T to implement some interface or inherit from some class, you should go for #snajahi's answer, which uses compile-time checks for that and genereally resembles a better approach to this problem.
You can use constraints on the class.
MyClass<T> where T : Employee
Take a look at http://msdn.microsoft.com/en-us/library/d5x73970.aspx
If you want to check during compilation: Error if if T does NOT implement the desired interface/class, you can use the following constraint
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
I hope that helps.
The correct syntax is
typeof(Employee).IsAssignableFrom(typeof(T))
Documentation
Return Value: true if c and the current Type represent the same type, or if the current Type is in the inheritance hierarchy of c, or if the current Type is an interface that c implements, or if c is a generic type parameter and the current Type represents one of the constraints of c, or if c represents a value type and the current Type represents Nullable<c> (Nullable(Of c) in Visual Basic). false if none of these conditions are true, or if c is null.
source
Explanation
If Employee IsAssignableFrom T then T inherits from Employee.
The usage
typeof(T).IsAssignableFrom(typeof(Employee))
returns true only when either
T and Employee represent the same type; or,
Employee inherits from T.
This may be intended usage in some case, but for the original question (and the more common usage), to determine when T inherits or implements some class/interface, use:
typeof(Employee).IsAssignableFrom(typeof(T))
What everyone really means is:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
because you can literally assign from an instance of a DerivedType to an instance of a BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
when
public class BaseType {}
public class DerivedType : BaseType {}
And some concrete examples if you're having trouble wrapping your head around it:
(via LinqPad, hence the HorizontalRun and Dump)
void Main()
{
// http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface
var b1 = new BaseClass1();
var c1 = new ChildClass1();
var c2 = new ChildClass2();
var nb = new nobase();
Util.HorizontalRun(
"baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
b1.IsAssignableFrom(typeof(BaseClass1)),
c1.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(ChildClass1)),
c2.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(ChildClass2)),
nb.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(nobase))
).Dump("Results");
var results = new List<string>();
string test;
test = "c1 = b1";
try {
c1 = (ChildClass1) b1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "b1 = c1";
try {
b1 = c1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "c2 = b1";
try {
c2 = (ChildClass2) b1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "b1 = c2";
try {
b1 = c2;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
results.Dump();
}
// Define other methods and classes here
public static class exts {
public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
return typeof(T).IsAssignableFrom(baseType);
}
}
class BaseClass1 {
public int id;
}
class ChildClass1 : BaseClass1 {
public string name;
}
class ChildClass2 : ChildClass1 {
public string descr;
}
class nobase {
public int id;
public string name;
public string descr;
}
Results
baseclass->baseclass
True
child1->baseclass
False
baseclass->child1
True
child2->baseclass
False
baseclass->child2
True
nobase->baseclass
False
baseclass->nobase
False
and
FAIL: c1 = b1
b1 = c1
FAIL: c2 = b1
b1 = c2
I believe syntax is: typeof(Employee).IsAssignableFrom(typeof(T));
Although IsAssignableFrom is the best way as others have stated, if you only need to check if a class inherits from another, typeof(T).BaseType == typeof(SomeClass) does the job too.
Alternate ways to tell if an object o inherits a class or implements an interface is to use the is and as operators.
If you want to only know if an object inherits a class or implements an interface, the is operator will return a boolean result:
bool isCompatibleType = (o is BaseType || o is IInterface);
If you want to use the inherited class or implemented interface after your test, the as operator will perform a safe cast, returning a reference to the inherited class or the implemented interface if compatible or null if not compatible:
BaseType b = o as BaseType; // Null if d does not inherit from BaseType.
IInterface i = o as IInterface; // Null if d does not implement IInterface.
If you have only the type T, then use #nikeee's answer.

Cast array of unknowClass to array of otherClass in c#

How Can I dynamically cast at runtime.That is I am passing a child class object in the parent class object.
public abstract class tObject
{
public tObject[] someMthode(){;}
}
public class myClass : tObject
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
I want
myClass mc=new myClass();
tObject to=mc;
myClass[] mcArray=(myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
but when check any element of mcArray is correct
if (mcArray[0] is myClass)
{
//return true and run this ;
}
In fact I want cast when a method return array of tObject according to the base class :
subClass[] mcArray=(subClass[])instanceOfsubClass.someMthode()
subClass or myClass and ... are unknown class , and i don't know theirs name.
Solution
public T[] Cast<T>(tObject[] mcArray ) where T : tObject
{
if (mcArray != null)
{
int cnt = mcArray.GetLength(0);
T[] t = new T[cnt];
for (int i = 0; i < cnt; i++)
{
t[i] = (T)mcArray[i];
}
return t;
}
return null;
}
Thanks all for replies.
C# does not support that kind of array conversion. C# does -- unfortunately! -- support dangerous array covariance. That is, if you had an array myClass[] then you could implicitly convert it to an array tObject[]. This means that you can do this:
Tiger[] tigers = new Tiger[10];
Animal[] animals = tigers;
animals[0] = new Turtle();
and now we have a turtle inside an array of tigers. This crashes at runtime.
That's bad enough, but you want it to go the other way -- I have an array of animals and I'd like it to be treated as an array of tigers. That does not work in C#.
As other answers have noted, you'll need to make a second array and copy the contents of the first to the second. There are a number of helper methods to do so.
Maybe?
myClass mc = new myClass();
tObject to = mc;
//myClass[] mcArray = (myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
var mcArray = Array.ConvertAll(mc.someMthode(), item => (myClass) item);
Well, you can call IEnumerable.Cast for that:
var myArr = mc.someMethod().Cast<MyClass>().ToArray();
As MyClass[] implements IEnumerable<MyClass>.
EDIT: What you want is quite dangerous. Look the following code:
subClass[] mcArray=(subClass[]) new BaseClass[] {...};
If this conversion would work we could now simply make the following also:
mcArray[0] = new AnotherClass();
Now you have an array of subClasses containin one item of AnotherClass also.
If you do not know the type at compile-time you cannot expect the compiler to provide any compile-time-logic for a type it doesn´t know. Thus casting to an unknown type and calling members on isn´t supported. However you may achieve this using reflection:
var runtimeType = myArr[0].GetType();
var mi = runtimeType.GetMethod("SomeMethod");
var value = mi.Invoke(myArr[0]);
This is similar to the call
var value = ((subClass)myArr[0]).SomeMethod();
Why not solve it one step up the chain and make someMethod (spelling corrected) generic:
public abstract class tObject<T> where T:tObject
{
public T[] someMethod(){;}
}
public class myClass : tObject<myClass>
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
now myClass.someMethod returns a myclass[] and that problem is solved. However, since I'm assuming that tObject does other things that just create an array of tObjects, it may cause other problems that aren't inferrable from the code you provided.
Plus it's not 100% foolproof. There's nothing stopping you (or someone else) from defining:
public class myWeirdClass : tObject<myClass>
{
}
now myWeirdClass.someMethod also returns a myClass[], and the pattern is broken. Unfortunately there's no generic constraint that requires that the generic parameter be the defining class itself, so there's no way to prevent this flaw at compile-time.
Another option may be to move the array creation outside of the class itself, since it is a code smell in itself:
public class ObjectFactory<T> where T:tObject
{
public T[] SomeMethod()
{
... create an array of Ts
}
}

Specifying "any subclass" in a C# type constraint rather than "one particular subclass"

If I would like to write a method that takes a variable number of "TDerived" where TDerived is any subclass of a class "Base", is there any way to do this?
The following code only works with a single specific specified subclass:
void doStuff<TDerived>(params TDerived[] args) where TDerived : Base
{
//stuff
}
ie if I have
class Super { }
class Sub0 : Super { }
class Sub1 : Super { }
then I cannot do
Sub0 s0 = new Sub0();
Sub1 s1 = new Sub1();
doStuff(s0, s1);
since I get "best overloaded match... has some invalid arguments".
Regardless of how the compiler handles the type constraints and variadic functions, this seems (as far as I can tell) completely type-safe. I know I could cast, but if this is type safe why not allow it?
EDIT:
Perhaps a more convincing example:
void doStuff<TDerived>(params SomeReadOnlyCollection<TDerived>[] args) where TDerived : Base
{
foreach(var list in args)
{
foreach(TDerived thing in list)
{
//stuff
}
}
}
TDerived needs to be able to resolve to a single type. In your example, the only type it could resolve to would be Super, but the compiler is not going to make that leap. You can make that leap for the compiler.
doStuff(new Super[] { s0, s1 });
doStuff<Super>(s0, s1);
Regarding your update, consider (instead of a generic method) defining a method accepting IEnumerable<ISuper>, which will support derived types because IEnumerable<T> is covariant (as of .NET 4). IEnumerable<T> is also inherently readonly and forward-only, perfect if you have a foreach loop. Full working example:
class Program
{
static void Main()
{
var sub0s = new Sub0[] { new Sub0() };
var sub1s = new List<Sub1> { new Sub1() };
doStuff(sub0s, sub1s);
}
static void doStuff(params IEnumerable<ISuper>[] args)
{
foreach (var sequence in args)
{
foreach (var obj in sequence)
{
Console.WriteLine(obj.GetType());
// you have the ability to invoke any method or access
// any property defined on ISuper
}
}
}
}
interface ISuper { }
class Super : ISuper { }
class Sub0 : Super { }
class Sub1 : Super { }
IEnumerable<T> is implemented by BCL collections since .NET 2.0, including T[], List<T>, ReadOnlyCollection<T>, HashSet<T>, etc.
In your example, you are actually telling the compiler that all arguments to doStuff must be of the same type at compile time, and that this type has to be inherited from Base. If you want to allow the arguments to be of different types, then just don't use generics:
void doStuff(params Base[] args)
{}
EDIT
The same applies with your new example - instead of a specific SomeReadOnlyCollection you can use IEnumerable, as it is covariant:
void doStuff(params IEnumerable<Base>[] args)
{
foreach (var list in args)
{
foreach (var thing in list)
{
}
}
}
Well you could most certainly change
Sub0 s0 = new Sub0();
Sub1 s1 = new Sub1();
To
Super s0 = new Sub0();
Super s1 = new Sub1();
and then it would work if Super is TDerived.
I may be misunderstanding you, but the only way to make a method take any subclass of a base class is to declare the method to take a reference to the base type.
One other alternative you could use is to simply specify the generic parameter explicitly. For example:
var s0 = new Sub0();
var s1 = new Sub1();
doStuff<Super>(s0, s1);
You should be able to apply the same principle on the case with SomeReadOnlyCollection, as long as it is covariant. For example, IEnumerable is such a collection:
static void doStuff2<TDerived>(params IEnumerable<TDerived>[] args) where TDerived : Super {
// ...
}
// ...
var l0 = new List<Sub0>();
var l1 = new List<Sub1>();
doStuff2<Super>(l0, l1);

Casting a generic element type downwards

public class ConfigControlBase<T> : UserControl
where T : ProviderBase
{
public T Provider { get; set; }
public void Init(T provider)
{
this.Provider = provider;
}
}
public abstract class ProviderBase
{
public abstract ConfigControlBase<ProviderBase> GetControl();
}
public class ProviderXConfigControl : ConfigControlBase<ProviderX>
{
}
public class ProviderX : ProviderBase
{
public override ConfigControlBase<ProviderBase> GetControl()
{
var confControl = new ProviderXConfigControl() as ConfigControlBase<ProviderX>;
return confControl;
}
}
return confControl; throws an exception:
Cannot implicitly convert type ConfigControlBase<ProviderX> to ConfigControlBase<ProviderBase>
Let's change the name of your classes and properties, but keep the shape the same:
public class Cage<T> where T : Animal
{
public T Contents { get; set; }
}
public class Aquarium : Cage<Fish> { }
public abstract class Animal
{
public abstract Cage<Animal> GetCage();
}
public class Fish : Animal
{
public override Cage<Animal> GetCage()
{
return (Cage<Animal>)(new Aquarium());
}
}
Now is it clear why this is not legal? Suppose it were legal. Then you could do this:
Fish fish = new Fish();
Cage<Animal> cage = fish.GetCage();
cage.contents = new Tiger();
And now you have a tiger in your aquarium. And no one wants that.
The compiler (or runtime) has to prevent this type error somehow; it chooses to prevent it as soon as possible. The earliest it can do so is on the type test for the conversion from Aquarium to Cage<Animal>. The compiler knows that this can eventually lead to tigers in aquariums, so it does not allow the conversion at all. If you force the compiler to allow it through casts then it fails at runtime.
Generic types with assignable type arguments are not assignable themselves.
For instance, you cannot cast List<string> to List<object>, although string is an object.
It is not immediately obvious why such casting is not supported so let me give you an example:
var words = new List<string> { "Serve God", "love me", "mend" };
var objects = (List<object>) words; // C# compiler wouldn't allow this
objects.Add (new Car()); // we just added a Car to Shakespeare's work and the universe exploded
C# doesn't encourage universe explosion, however since C# 4.0 a light version of this idea is implemented. You see, in some cases such casting would actually be safe.
.NET 4.0 brings concepts of covariance and contravariance in generics only for interfaces and delegates, you may want to check this out.
Example (doesn't work prior to .NET 4.0):
void HandleCollection (IEnumerable<object> collection)
{
// ...
}
var words = new List<string> { "Serve God", "love me", "mend" };
// IEnumerable is defined as IEnumerable<out T> in .NET 4.0
// 'out' keyword guarantees that T is only used for return values
// and therefore client code can't explode the universe
var objects = (IEnumerable<object>) words;
HandleCollection (objects);
This is because ConfigControlBase<ProviderX> is not a ConfigControlBase<ProviderBase>
your
public override ConfigControlBase<ProviderBase> GetControl()
doesn't match
var confControl = new ProviderXConfigControl() as ConfigControlBase<ProviderX>;
This answer might not be useful in your scenario, as you should probably look for another solution, but during reflection I found the ability to cast to less generic types very useful, hence I wrote a solution for it. It only works for interfaces however, and you do have to guarantee you will only pass objects of the correct types to the interface.
I basically generate a proxy class at runtime which does all the required casts for you. It's usage looks as follows:
object validator; // An object known to implement IValidation<T>.
object toValidate; // The object which can be validated by using the validator.
// Assume validator is IValidation<string> and toValidate a string.
IValidation<object> validation
= Proxy.CreateGenericInterfaceWrapper<IValidation<object>>( validator );
validation.IsValid( toValidate ); // This works! No need to know about the type.
// The following will throw an InvalidCastException.
//validation.IsValid( 10 );
More information and source code can be found on my blog.

Adding generic object to generic list in C#

I have class where the relevant part looks like
class C {
void Method<T>(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
How should I define the list so that the class compiles?
I want a list of type List<SomeClass<?>>, that is a list of objects of SomeClass where each object can have any type parameter. The Java ? construct allows this; what is the C# equivalent? If no such thing exists, is there a suitable workaround? (A List<object> would do but is terribly ugly.)
I don't think you can do this in C#... you would have to add the type parameter to the class:
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<SomeClass<T>> list = new List<SomeClass<T>>();
}
The other option would be to use an interface:
class C {
void Method<T>(T obj)
where T : ISomeClass {
list.Add(obj);
}
List<ISomeClass> list = new List<ISomeClass>();
}
To do what you want, you have two options.
You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.
Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.
Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant.
You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature.
To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead.
If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.
I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.
class SomeClass<T>
{
}
class C
{
void Add<T>(SomeClass<T> item)
{
Type type = typeof(SomeClass<T>);
if (!list.ContainsKey(type))
list[type] = new List<SomeClass<T>>();
var l = (List<SomeClass<T>>)list[type];
l.Add(item);
}
public void Method<T>(SomeClass<T> obj)
{
Add(obj);
}
readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
}
test it with the following:
class Program
{
static void Main(string[] args)
{
var c = new C();
var sc1 = new SomeClass<int>();
var sc2 = new SomeClass<String>();
c.Method(sc1);
c.Method(sc2);
c.Method(sc1);
c.Method(sc2);
}
}
Personally, I would do this where possible; move the generic parameter from the method, to the class.
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<?> list = new List<?>();
}
If your generic list is a member, it stands to reason that the class should be constructed with this in mind. It is hard for us to suggest the best pattern without more usage context for the class.

Categories

Resources