How to get base class object from closed constructed class in C# - c#

Just another small C# training app, and just another Compilation Error, but it cannot just go away from me... I am just wondering, what I am doing wrong here:
public abstract class Material
{
}
public abstract class Cloth<T> where T:Material
{
public T Prop { get; set; }
}
public class Cotton : Material
{
}
public class Dress<T> : Cloth<T> where T : Material
{
}
public class Test
{
private Cloth<Material> cloth;
public Test()
{
/* below won't compile */
cloth = new Dress<Cotton>();
}
}
I want to get the base class object from a closed constructed class. Anyone ?
When trying to compile I get the error:
Cannot implicitly convert type Dress<Cotton> to Cloth<Material>

What you want to achieve is called covariance (see the following article for samples).
Unfortunately, there's no variance support for classes: it's restricted to interfaces and delegates.
Thus and alternatively, you might design an interface called ICloth<T> with T covariant:
public interface ICloth<out T>
{
T Prop { get; set; }
}
And implement it in any of your possible cloths, including Cloth<T>.
Now type cloth as ICloth<T> and your assignment should work (i.e. cloth = new Dress<Cotton>();), because Dress<Cotton> is ICloth<out T>, which is an interface with a T covariant generic parameter.
Learn more about generic interface with variance in the following article on MSDN.

Related

Check if object implements a specific generic interface [duplicate]

This question already has answers here:
How to determine if a type implements a specific generic interface type
(14 answers)
Check if a type implements a generic interface without considering the generic type arguments
(2 answers)
Closed 1 year ago.
Background
My code base currently has the following interfaces and classes:
// Both DisplayValue _classes_
public class DisplayValue<T>
{
public T Value { get; set; }
}
public class DisplayValue : DisplayValue<object> {}
// Both IValueWidget _interfaces_
public interface IValueWidget<T>
{
DisplayValue<T> Value { get; set; }
}
public interface IValueWidget: IValueWidget<object>
{
new DisplayValue Value { get; set; }
}
// the BaseWidget all other widgets implement
public interface IBaseWidget
{
public string Name { get; set; }
}
The code base also has a bunch of Widgets, all of which implement IBaseWidget. Some also implement IValueWidget or IValueWidget<T>, which leads me to my problem.
Problem
Say I have the following method:
public T2 DoStuff<T2>(T2 widget) where T2 : IBaseWidget
{
// this should check if the widget is the correct type
if (widget is IValueWidget)
{
}
}
In that method, I would like to have the condition work with either IValueWidget or any generic version of IValueWidget. I don't care whatsoever what the type of T is, only that the given T2 can be treated as such.
Also worth mentioning, literally no types other than the ones provided above are known at compile time. Everything must work at runtime.
In Java, I could do something like this but obviously C# does not have wildcards.
public T2 DoStuff<T2 extends IBaseWidget>(T2 widget) {
if (widget instanceof IValueWidget<?>) {
}
}
Notes
As far as I can tell, this is not actually a duplicate. Please don't flag it as such if you're referring to any of these, as they are similar but definitely not the same:
Check if object implements specific generic interface
Wildcard equivalent in C# generics
Get interfaces implemented by class

Why I cannot implement an interface on a class replacing an interface with a concrete type? [duplicate]

This question already has answers here:
The return type of the members on an Interface Implementation must match exactly the interface definition?
(6 answers)
Does C# support return type covariance?
(9 answers)
Closed 8 years ago.
Why can I not do the following?
public class TestClass : TestInterface
{
public ClassX Property { get; private set; }
}
public interface TestInterface
{
InterfaceX Property { get; }
}
public interface InterfaceX
{
}
public class ClassX : InterfaceX
{
}
The TestInterface Property is readonly, thus can only return InterfaceX as per the contract.
However, I get this compiler error:
'TestClass' does not implement interface member
'TestInterface.InterfaceX'. 'TestClass.InterfaceX' cannot implement
'TestInterface.InterfaceX' because it does not have the matching
return type of 'InterfaceX'.
It does not have the matching type but it has a subclass of that type.
I don't know the spec offhand, but I'm sure there's one that explicitly states that return types must match exactly for interface implementations. The closest I can find is 13.4.4:
For purposes of interface mapping, a class member A matches an interface member B when:
A and B are methods, and the name, type, and formal parameter lists of A and B are identical.
A and B are properties, the name and type of A and B are identical, and A has the same accessors as B (A is permitted to have additional accessors if it is not an explicit interface member implementation).
If "type" above means "return type" that would indicate that the return type cannot change.
You could, however, change the return type and explicitly implement the interface with the right return type:
public class TestClass : TestInterface
{
public ClassX InterfaceX { get; private set; }
InterfaceX TestInterface.InterfaceX { get { return InterfaceX; } }
}
UPDATE
According to Eric Lippert it seems to be a CLR limitation, not just a C# one.
You mentioned that you want to expose a reduced set but you want all the functionality internal to the class -- that's not what you want to use an interface for. An interface should only be about your reduced set contract, not also magically function as a full set internally, not without another helper property.
But, there is a way around this limitation while still communicating the contract a little.
interface IExpose<IToolType> where IToolType : ITool
{
IToolType Handler { get; set; }
}
class Expose : IExpose<Tool>
{
public Tool Handler { get; set; }
}
interface ITool
{
}
class Tool : ITool
{
}

Using covariance outside the context of IEnumerable<T> [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does C# support return type covariance?
Why can’t I implement an Interface this way?
Consider the following:
public interface IAnimal {
}
public class Animal : IAnimal {
}
public interface ICage {
IAnimal SomeAnimal {get;}
}
public class Cage : ICage{
public Animal SomeAnimal { get; set; }
}
I've read a lot of stuff on covariance and contravariance for IEnumerable, but I'm not sure how to get the above code to work. I get the error "Cage does not implement interface member IAnimal". Since it defined Animal, which is more defined than IAnimal, it seems like covariance should take care of me.
What am I missing? Thanks in advance.
That's not currently possible in C#.
It theoretically possible for the language designers to add it, they just haven't [yet]. They may or may not decide to add it to a potential future version of C#.
The best workaround would probably be:
public class Cage : ICage
{
public Animal SomeAnimal { get; set; }
IAnimal ICage.SomeAnimal
{
get { return SomeAnimal }
}
}
Quoted from Eric Lippert, in response to me asking the same question here:
Why can't I implement an Interface this way?
C# does not support return type covariance for the purposes of
interface implementation or virtual method overrding. See this
question for details:
Does C# support return type covariance?
C# does support generic covariance and contravariance of interfaces
and delegate types that are constructed wtih reference types for the
type arguments as of C# 4.
And C# does support return type covariance when converting a method
that returns a reference type to a delegate type whose return type is
a compatible reference type. (And similarly it supports parameter type
contravariance.)
If this subject interests you, I have written a great many articles
discussing various versions of variance that C# does and does not
support. See
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
for details.
To get covariance you should have something like this:
public interface IAnimal {
}
public class Lion : IAnimal {}
public class Sheep : IAnimal {}
// note the "out" on the T type parameter
public interface ICage<out T> where T:IAnimal {
T SomeAnimal {get;}
}
public class Cage<T> : ICage<T> where T:IAnimal {
public T SomeAnimal { get; set; }
}
you can now do this:
// without covariance on ICage you can't assign a 'Cage<Sheep>' to 'ICage<IAnimal>'
ICage<IAnimal> sheeps = new Cage<Sheep>() {SomeAnimal=new Sheep()};
ICage<IAnimal> lions = new Cage<Lion>() {SomeAnimal=new Lion()};
or this (creating a heterogeneous list of Cage<IAnimals> with both Cages of Sheeps and Cages of Lions), which is an equivalent but probably more useful example:
// without covariance on ICage it errors: cannot convert from 'Cage<Sheep>' to 'ICage<IAnimal>'
var zoo = new List<ICage<IAnimal>>{
new Cage<Sheep> {SomeAnimal=new Sheep()},
new Cage<Lion> {SomeAnimal=new Lion()},
};
if you try removing the out from the declaration of ICage you will see the difference.
public interface IAnimal {
}
public class Animal : IAnimal {
}
public interface ICage {
IAnimal SomeAnimal {get;}
}
public class Cage : ICage{
public Animal SomeAnimal { get; set; }
}
public class AnotherAnimal : IAnimal {
}
Cage c = new Cage();
ICage ic = (ICage)c;
ic.Animal = new AnotherAnimal();
this would be invalid because AnotherAnimal implements IAnimal, but it is not an Animal.
EDIT
the above would only be relevant if there was a setter defined in the interface. Because there is not, the proper answer here is that the desired functionality cannot be achieved in C#; it is a feature not included in the language.

c# covariant return types utilizing generics

Is the code below the only way to implement covariant return types?
public abstract class BaseApplication<T> {
public T Employee{ get; set; }
}
public class Application : BaseApplication<ExistingEmployee> {}
public class NewApplication : BaseApplication<NewEmployee> {}
I want to be able to construct an Application or a NewApplication and have it return the appropriate Employee type from the Employee property.
var app = new Application();
var employee = app.Employee; // this should be of type ExistingEmployee
I believe this code works fine, but it gets really nasty when I have several properties that require the same behavior.
Are there any other ways to implement this behavior? Generics or otherwise?
UPDATE: This answer was written in 2010. After two decades of people proposing return type covariance for C#, it looks like it will finally be implemented; I am rather surprised. See the bottom of https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ for the announcement; I'm sure details will follow. The portions of the answer below which speculate on the possibility of the feature being implemented should be considered of historical interest only going forwards.
First off, the answer to your question is no, C# does not support any form of return type covariance on virtual overrides.
A number of answerers and commenters have said "there is no covariance in this question". This is incorrect; the original poster was entirely correct to pose the question as they did.
Recall that a covariant mapping is a mapping which preserves the existence and direction of some other relation. For example, the mapping from a type T to a type IEnumerable<T> is covariant because it preserves the assignment compatibility relation. If Tiger is assignment compatible with Animal, then the transformation under the map is also preserved: IEnumerable<Tiger> is assignment compatible with IEnumerable<Animal>.
The covariant mapping here is a little bit harder to see, but it is still there. The question essentially is this: should this be legal?
class B
{
public virtual Animal M() {...}
}
class D : B
{
public override Tiger M() {...}
}
Tiger is assignment-compatible with Animal. Now make a mapping from a type T to a method "public T M()". Does that mapping preserve compatibility? That is, if Tiger is compatible with Animal for the purposes of assignment, then is public Tiger M() compatible with public Animal M() for the purposes of virtual overriding?
The answer in C# is "no". C# does not support this kind of covariance.
Now that we have established that the question has been asked using the correct type algebra jargon, a few more thoughts on the actual question. The obvious first problem is that the property has not even been declared as virtual, so questions of virtual compatibilty are moot. The obvious second problem is that a "get; set;" property could not be covariant even if C# did support return type covariance because the type of a property with a setter is not just its return type, it is also its formal parameter type. You need contravariance on formal parameter types to achieve type safety. If we allowed return type covariance on properties with setters then you'd have:
class B
{
public virtual Animal Animal{ get; set;}
}
class D : B
{
public override Tiger Animal { ... }
}
B b = new D();
b.Animal = new Giraffe();
and hey, we just passed a Giraffe to a setter that is expecting a Tiger. If we supported this feature we would have to restrict it to return types (as we do with assignment-compatibility covariance on generic interfaces.)
The third problem is that the CLR does not support this kind of variance; if we wanted to support it in the language (as I believe managed C++ does) then we would have to do some reasonably heroic measures to work around signature matching restrictions in the CLR.
You can do those heroic measures yourself by carefully defining "new" methods that have the appropriate return types that shadow their base class types:
abstract class B
{
protected abstract Animal ProtectedM();
public Animal Animal { get { return this.ProtectedM(); } }
}
class D : B
{
protected override Animal ProtectedM() { return new Tiger(); }
public new Tiger Animal { get { return (Tiger)this.ProtectedM(); } }
}
Now if you have an instance of D, you see the Tiger-typed property. If you cast it to B then you see the Animal-typed property. In either case, you still get the virtual behaviour via the protected member.
In short, we have no plans to ever do this feature, sorry.
There might be multiple problems with what you try to achieve.
First of all, as somebody already noticed, there is no covarianace in your example. You can find a short description of covariance and generics here, new features in C# 2.0 - Variance, covariance on generics.
Secondly it seems that you try to solve with generics what should be solved with polymorphism. If both ExistingEmployee and NewEmployee inherit from a base class Employee, your problem would be solved:
public class Application {
public ExistingEmployee Employee { get; }
}
public class NewApplication {
public NewEmployee Employee { get; }
}
...
Application app = new Application;
var emp = app.Employee; // this will be of type ExistingEmployee!
Please note that the below is also true:
Employee emp = app.Employee; // this will be of type ExistingEmployee even if
// declared as Employee because of polymorphism
The one thing that would be different between polymorphism and generics, would be that if you return the variable to the specific type you would need a cast in the later case:
ExistingEmployee emp = (ExistingEmployee)app.Employee; // would have not been needed
// if working with generics
Hope this helps.
You could code against an Employee Interface to get what you want I think.
public interface IEmployee
{}
public abstract class BaseApplication<T> where T:IEmployee{
public T IEmployee{ get; set; }
}
public class ExistingEmployee : IEmployee {}
public class NewEmployee : IEmployee {}
public class Application : BaseApplication<ExistingEmployee> {}
public class NewApplication : BaseApplication<NewEmployee> {}
The code you posted will not compile but I get the basic idea of what you want to do. In short the answer is yes, that is the only way. If you want a property to return different types and be typed differently in extended classes then you have to use generics in the way that you already are.
If you can encapsulate the public contract of an employee object, new or existing, into an interface then you don't need to use generics at all. Instead you can just return the interface and let polymorphism take over.
public interface IEmployee
{ }
public class Employee1 : IEmployee
{ }
public class Employee2 : IEmployee
{ }
public abstract class ApplicationBase
{
public abstract IEmployee Employee { get; set; }
}
public class App1 : ApplicationBase
{
public override IEmployee Employee
{
get { return new Employee1(); }
set;
}
}
public class App2 : ApplicationBase
{
public override IEmployee Employee
{
get { return new Employee2(); }
set;
}
}
You can achieve a somewhat neat looking version of this using generics.
Covariant return types are not supported by c#. So this is not a solution, however, my feeling is that syntactically speaking this reads well. It does achieve a similar result.
I find it useful when creating fluent API's where the base class needs to perform some actions, but I need the derived implementation back. All it really achieves is to hide the cast.
public class Base
{
public virtual T Foo<T>() where T : Base
{
//... // do stuff
return (T)this;
}
}
public class A : Base
{
public A Bar() { "Bar".Dump(); return this; }
public A Baz() { "Baz".Dump(); return this; }
// optionally override the base...
public override T Foo<T>() { "Foo".Dump(); return base.Foo<T>(); }
}
var x = new A()
.Bar()
.Foo<A>() // cast back to A
.Baz();
Opinions will vary, and it's not 100% pretty. It's probably not appropriate for an API that will be published, but for internal use, for instance in unit tests, I find it useful.
YES!! Like this. There is more boiler plate than you would hope for, but it does work. The trick is done with extension methods.
It dose some nasty casting internally, but presents a covariant interface.
See also: http://richarddelorenzi.wordpress.com/2011/03/25/return-type-co-variance-in-c/
using System;
namespace return_type_covariance
{
public interface A1{}
public class A2 : A1{}
public class A3 : A1{}
public interface B1
{
A1 theA();
}
public class B2 : B1
{
public A1 theA()
{
return new A2();
}
}
public static class B2_ReturnTypeCovariance
{
public static A2 theA_safe(this B2 b)
{
return b.theA() as A2;
}
}
public class B3 : B1
{
public A1 theA()
{
return new A3();
}
}
public static class B3_ReturnTypeCovariance
{
public static A3 theA_safe(this B3 b)
{
return b.theA() as A3;
}
}
public class C2
{
public void doSomething(A2 a){}
}
class MainClass
{
public static void Main (string[] args)
{
var c2 = new C2();
var b2 = new B2();
var a2=b2.theA_safe();
c2.doSomething(a2);
}
}
}
One idea without generics, but it has other downsides:
public abstract class BaseApplication {
public Employee Employee{ get; protected set; }
}
public class Application : BaseApplication
{
public new ExistingEmployee Employee{ get{return (ExistingEmployee)base.Employee;} set{base.Employee=value; }}
}
public class NewApplication : BaseApplication
{
public new NewEmployee Employee{ get{return (NewEmployee)base.Employee;} set{base.Employee=value; }}
}
In particular with this code you can cast to the base class and assign an employee of an undesirable type. So you need to add checks against that in the setter of the base-class. Or remove the setter, which I usually prefer anyways. one way to do that is making the setter protected.
Another is adding a virtual function EmployeeType() which you override in derived classes and return a derived type. Then you check in the setter if EmployeeType().IsInstanceOf(value) and else throw an exception.
And IMO simulating covariant return types is one of the few good applications of the new marker. It returns the same thing as the base-class and just adds additional guarantees to the function contract.

polymorphism for properties specified by interfaces

Why doesnt this work?
public class ClassOptions {}
public interface Inode {
ClassOptions Options {get;}
}
public class MyClass : Inode {
public ClassOptions Options { get; set; }
}
public class ClassDerivedOptions : ClassOptions {
}
public class MyDerivedClass : Inode {
public ClassDerivedOptions Options { get; set; } << does not implement INode...
}
[ the compiler message tells me why it breaks but i'd like to know the reasoning behind why the compiler doesnt let this through - also if there are any work arounds? - thanks]
It doesn't work because the INode interface explicitly calls for an Options property of type ClassOptions. C# doesn't support return type covariance (which is what you're asking for in this case).
For what it's worth, there's also a language feature request on Microsoft Connect specifically for return type covariance:
Need covariant return types in C# / all .NET languages
If you look at the page, they also mention that the common work-around is to use Explicit Interface Implementation:
public class MyDerivedClass : INode
{
public ClassDerivedOptions Options { get; set; }
public ClassOptions INode.Options { get { return Options; } }
}
As Justin notes, the feature you want is called "return type covariance" and it is not supported in C#, or, for that matter, in the CLR type system.
Though it is frequently requested, it is extremely unlikely (*) that this feature will be implemented any time soon. Since it is not supported in the CLR, in order to implement it we would simply have to generate all the helper methods that do the call forwarding for you. Since you can already do that "manually" with a small amount of code, there is little value added by the compiler doing it for you. (And as another question today notes, people sometimes get confused or irritated when the compiler generates a method to do interface forwarding on your behalf.)
Don't get me wrong; I can see how it comes in handy, and I've used this feature in C++. But every time it has come up in a C# program, I've found I can work around its absence pretty easily.
(*) Of course five years ago I would have said exactly the same thing about named and optional parameters, and now they're in C# 4. It is possible for an unlikely feature to be implemented, but the demand has to be pretty darn high.
It doesn't work because an interface defines a contract and when you implement this contract method signatures must match exactly. A possible workaround is to use a generic interface:
public class ClassOptions
{ }
public class ClassDerivedOptions : ClassOptions
{ }
public interface INode<T> where T : ClassOptions
{
T Options { get; }
}
public class MyClass : INode<ClassOptions>
{
public ClassOptions Options { get; set; }
}
public class MyDerivedClass : INode<ClassDerivedOptions>
{
public ClassDerivedOptions Options { get; set; }
}
The standard way to deal with this situation is to implement the interface explicitly:
public class MyDerivedClass : Inode {
// New, more specific version:
public ClassDerivedOptions Options { get; set; }
// Explicit implementation of old, less specific version:
ClassOptions Inode.Options
{
get { return Options; }
}
}
This is how most old IList implementations worked before generics, for example: specifying a more specific T this[int index] property and then explicitly implementing object IList.this[int index], throwing an exception when the set got called with an object of the wrong type.
In the example code you posted, you don't even need an explicit set, as that is not a member of your Inode interface.

Categories