Converting Wrapper<Derived> to Wrapper<Base> - c#

I have code like this:
class Base { }
class Derived : Base { }
class Wrapper<T> {
public T Value { get; }
public Wrapper (T value) { Value = value; }
}
I would like to use Wrapper like this:
Wrapper<Base> wrapper = new Wrapper<Derived> (new Derived ());
But it ends up with this error:
Error CS0029 Cannot implicitly convert type 'Wrapper<Derived>' to 'Wrapper<Base>'
I tried creating method in Wrapper class that would act as converter
public Wrapper<TResult> To<TResult> () /* Constraints needed here. */ =>
new Wrapper<TResult> (Value);
But I'm missing some valid constraints. Current code ends up with error:
S1503 Argument 1: cannot convert from 'T' to 'TResult'
I would imagine constraints on To method could look like where T : TResult, but that's not valid constraints.
Any ways to implement converter from Wrapper<Derived> to Wrapper<Base> easily?

You could use covariance like so:
class Base { }
class Derived : Base { }
interface IWrapper<out T>
{
T Value { get; }
}
class Wrapper<T> : IWrapper<T>
{
public T Value { get; private set; }
public Wrapper(T value) { Value = value; }
}
class Program
{
static void Main(string[] args)
{
IWrapper<Base> wrapper = new Wrapper<Derived>(new Derived());
}
}

At first I would add a constraint to the class demanding that T must be of type Base:
class Base { }
class Derived : Base { }
class Wrapper<T> where T : Base // T must be (derived from) Base
{
public T Value { get; }
public Wrapper (T value) { Value = value; }
}
Secondly, a generic converter would be dangerous. What if someone tries to convert a Wrapper<Gnu> to a Wrapper<Lion>?
So I'd take a step back and make a non-generic converter that simply converts to Wrapper<Base>:
public Wrapper<Base> ToBase()
{
return new Wrapper<Base>(Value);
}
And this works because of the constraint for T at class level.
C# is actually a language known for a high level of type safety. But you can get around it and do what you asked for in the comment by ommitting any constraints and just trying to cast whatever comes in:
public Wrapper<TResult> To<TResult>() where TResult : class
{
return new Wrapper<TResult>(Value as TResult);
}
You need the class constraint and the as operator because a direct cast between two generic parameters is not compilable (as the IL depends too much on the specific types).
But this will return Wrapper instances with Value set to null if the types don't match. And it will work with derived types instead of base types too. So take care. You may add some extra checks for that. And take care of the gnus :)
UPDATE:
A safer way:
public Wrapper<TResult> To<TResult>() where TResult : class// TResult must also be (derived from) Base
{
if (!typeof(TResult).IsAssignableFrom(typeof(T)))
throw new InvalidCastException();
return new Wrapper<TResult>(Value as TResult);
}
This checks that T is derived from TResult and throws an InvalidCastException if not. You may refine that for your needs.

The problem you're encountering is that the generic types Wrapper<Base> and Wrapper<Derived> are two completely different classes for the .NET Framework
What you could do is creating a new Wrapper of type Base:
Wrapper<Base> wrapper = new Wrapper<Base>(new Derived());
Or to complete your To-method approach:
public Wrapper<TResult> To<TResult>() where TResult : T
=> new Wrapper<TResult>( (TResult)Value ); // This could throw an error
public bool TryCastTo<TResult>(out Wrapper<TResult> derivedWrapper) where TResult : T
{
derivedWrapper = null;
// EDIT: changed to the version from René Vogt since this is much cleaner and mine had a little error
if (!typeof(T).IsAssignableFrom(typeof(TResult)))
{
return false;
}
derivedWrapper = new Wrapper<TResult>( (TResult)Value );
return true;
}
The usage would be:
Wrapper<Derived> derivedWrapper1 = wrapper.To<Derived>();
Wrapper<Derived> derivedWrapper2;
bool success = wrapper.TryCastTo<Derived>(out derivedWrapper2);

Related

Why my convarian (out keyword) not working?

How to use the Covariance(out keyword)?I have no idea.
I know out keyword in Interface mean Covariance that allow you use a more derived type than that specified by the generic parameter.
So i set generic to object and return type to string.Because string is subclass of object.
But i tried and it not working.
public interface IMyInterface<out T>
{
public T Foo();
}
public class CovarianceTest : IMyInterface<object>
{
public string Foo()
{
return "abc";
}
}
Covariance that allow you use a more derived type than that specified by the generic parameter
That's not what it means. You still have to write methods that match the types in the interface. So you will have to do this:
public class CovarianceTest : IMyInterface<string>
{
public string Foo()
{
return "abc";
}
}
What covariance allow you to do is assign the class instance to a variable typed as a less specific interface, like this:
IMyInterface<object> x = new CovarianceTest();
Console.WriteLine(x.Foo());
That's because all Ts read from the interface (i.e. taken out) are guaranteed to be instances that are type-compatible with the less specific type, i.e. all strings are also objects.
I suspect you are trying to do the following.
public interface IMyInterface<out T>
{
public T Foo();
}
public class CovarianceTest : IMyInterface<string>
{
public string Foo()
{
return "abc";
}
}
IMyInterface<string> works = new CovarianceTest();
IMyInterface<object> alsoWorks = new CovarianceTest();
IMyInterface<int> doesNotWork = new CovarianceTest();

Why does ReSharper suggest that I make type parameter T contravariant?

ReSharper suggests me to make type parameter T contravariant by changing this:
interface IBusinessValidator<T> where T: IEntity
{
void Validate(T entity);
}
Into this:
interface IBusinessValidator<in T> where T: IEntity
{
void Validate(T entity);
}
So what is different between <T> and <in T>? And what is the purpose of contravariant here?
Let say I have IEntity, Entity, User and Account entities. Assuming that both User and Account have Name property that need to be validated.
How can I apply the usage of contravariant in this example?
So what is different between <T> and <in T>?
The difference is that in T allows you to pass a more generic (less derived) type than what was specified.
And what is the purpose of contravariant here?
ReSharper suggests to use contravariance here because it sees the you're passing the T parameter into the Validate method and wants to enable you to broaden the input type by making it less generic.
In general, contravariance is explained to length in Contravariance explained and in Covariance and contravariance real world example, and of course throughout the documentation on MSDN (there is a great FAQ by the C# team).
There is a nice example via MSDN:
abstract class Shape
{
public virtual double Area { get { return 0; }}
}
class Circle : Shape
{
private double r;
public Circle(double radius) { r = radius; }
public double Radius { get { return r; }}
public override double Area { get { return Math.PI * r * r; }}
}
class ShapeAreaComparer : System.Collections.Generic.IComparer<Shape>
{
int IComparer<Shape>.Compare(Shape a, Shape b)
{
if (a == null) return b == null ? 0 : -1;
return b == null ? 1 : a.Area.CompareTo(b.Area);
}
}
class Program
{
static void Main()
{
// You can pass ShapeAreaComparer, which implements IComparer<Shape>,
// even though the constructor for SortedSet<Circle> expects
// IComparer<Circle>, because type parameter T of IComparer<T> is
// contravariant.
SortedSet<Circle> circlesByArea =
new SortedSet<Circle>(new ShapeAreaComparer())
{ new Circle(7.2), new Circle(100), null, new Circle(.01) };
foreach (Circle c in circlesByArea)
{
Console.WriteLine(c == null ? "null" : "Circle with area " + c.Area);
}
}
}
How can I apply the usage of contravariant in this example?
Let's say we have our entities:
public class Entity : IEntity
{
public string Name { get; set; }
}
public class User : Entity
{
public string Password { get; set; }
}
We also have a IBusinessManager interface and a BusinessManager implementation, which accepts an IBusinessValidator:
public interface IBusinessManager<T>
{
void ManagerStuff(T entityToManage);
}
public class BusinessManager<T> : IBusinessManager<T> where T : IEntity
{
private readonly IBusinessValidator<T> validator;
public BusinessManager(IBusinessValidator<T> validator)
{
this.validator = validator;
}
public void ManagerStuff(T entityToManage)
{
// stuff.
}
}
Now, lets say we created a generic validator for any IEntity:
public class BusinessValidator<T> : IBusinessValidator<T> where T : IEntity
{
public void Validate(T entity)
{
if (string.IsNullOrWhiteSpace(entity.Name))
throw new ArgumentNullException(entity.Name);
}
}
And now, we want to pass BusinessManager<User> an IBusinessValidator<T>. Because it is contravariant, I can pass it BusinessValidator<Entity>.
If we remove the in keyword, we get the following error:
If we include it, this compiles fine.
To understand ReSharper's motivation, consider Marcelo Cantos's donkey gobbler:
// Contravariance
interface IGobbler<in T> {
void gobble(T t);
}
// Since a QuadrupedGobbler can gobble any four-footed
// creature, it is OK to treat it as a donkey gobbler.
IGobbler<Donkey> dg = new QuadrupedGobbler();
dg.gobble(MyDonkey());
If Marcelo had forgotten to use the in keyword in the declaration of his IGobbler interface, then C#'s type system wouldn't recognise his QuadrupedGobbler as a donkey gobbler, and so this assignment from the code above would fail to compile:
IGobbler<Donkey> dg = new QuadrupedGobbler();
Note that this wouldn't stop the QuadrupedGobbler from gobbling donkeys - for instance, the following code would work:
IGobbler<Quadruped> qg = new QuadrupedGobbler();
qg.gobble(MyDonkey());
However, you wouldn't be able to assign a QuadrupedGobbler to a variable of type IGobbler<Donkey> or pass it to some method's IGobbler<Donkey> parameter. This would be weird and inconsistent; if the QuadrupedGobbler can gobble donkeys, then doesn't that make it a kind of donkey gobbler? Luckily, ReSharper notices this inconsistency, and if you leave out the in in the IGobbler declaration, it will suggest that you add it - with the suggestion "Make type parameter T contravariant" - allowing a QuadrupedGobbler to be used as an IGobbler<Donkey>.
In general, the same logic outlined above applies in any case where an interface declaration contains a generic parameter that is only used as the type of method parameters, not return types.

C# and casting generic parameter

I'm coming from C++ template programming and get very confused with generics sometimes. As there is no method specialization, I tried using casting. Here's what I have:
public interface INonGen
{
void Get<T>(ref T value);
}
public interface IGen<U> : INonGen
{
}
public class Gen<U> : IGen<U>
{
private U u;
public void Get<T>(ref T value)
{
if (value is U)
{
value = (T) u;
}
else
throw new Exception();
}
}
This doesn't compile.
Is there I way I can make this cast?
The reason why I want this: With C++ templates, I would have made specializations for the types supported, and a non-specialied version that throws an exception.
The basic idea is this: A non-generic interface that has a generic method. Attempts to get the value using the correct type should work, attempts to use the wrong type can throw.
We should keep type safety, so I need to return an instance/value of the correct type. Any shortcuts over object are not acceptable, and neither is constraining the type in the non-generic interface.
The generic implementation is done to avoid duplication. I want to support multiple different types (but only a small set of types), but I want this to be decided when I instantiate a class (and define what T means); I still want the non-generic interface to allow access using any T; that is, I don't want the set of types explicitly in the interface.
When you cast an object to another, if the compiler can't find a conversion, it reports an error. Since the two type parameters are unconstrained, the only option is to use the as operator, which, instead of throwing an InvalidCastException, returns null when the cast fails. To use as you also need to constrain your generic type to classes.
public class Gen<U> : IGen<U>
{
private U u;
public void Get<T>(ref T value)
where T : class
{
if (value is U)
{
value = u as T;
}
else
throw new Exception();
}
}
If you don't want to add the constraint, you can cast to Object:
value = (T)(object)u;
There's a logical error in your code though. If value is U, what guarantees that u is T? For example:
var gen = new Gen<Base>();
gen.Set(new DerivedA()); // sets u;
var b = new DerivedB();
gen.Get(ref b);
In this case value is Base but not u is DerivedB. The cast will fail at runtime.
Update
After reading some of your comments, here's how I would've designed this:
public interface INonGen
{
object Value { get; }
}
public interface IGen<U> : INonGen
{
}
public class Gen<U> : IGen<U>
{
private U u;
public object Value
{
get { return u; }
}
}
And when pulling items out of the dictionary:
double value = (double)dictionary[key].Value;
An InvalidCastException will be thrown if there's no runtime conversion. Simple, no?
I'm not sure what the purpose of INonGen is in this context, especially as it has a generic method. If you get rid of that you can do this. Which compiles - I checked ;o)
public interface IGen<T>
{
void Get(ref T value);
}
public class Gen<T, U> : IGen<T> where U : T
{
private U u;
public void Get(ref T value)
{
if (value is U)
{
value = (T)u;
}
else
throw new Exception();
}
}
The point is that you cannot have the generic type argument on the interface method only, because that prevents you from specifying the U : T constraint in the implementing class. It has to be on the interface definition itself. And the implementing class has to know explicitly about both generic type arguments U and T, so that the compiler can verify the cast operation.
You could go down the route of using as but this is not type safe, so you have to handle cases where the result is null, rather than relying on the compiler to do it. Not recommended.
If in your real world example, INonGen has other non-generic methods, or generic methods where implementing classes do not need to know about the method's generic type arguments outside of the implementing method then you could reinstate it without any problems.
public interface INonGen
{
void NonGenericMethod();
void GenericMethod<V>(V parameter);
}
public interface IGen<T> : INonGen
{
void Get(ref T value);
}
public class Gen<T, U> : IGen<T> where U : T
{
private U u;
public void Get(ref T value)
{
if (value is U)
{
value = (T)u;
}
else
throw new Exception();
}
public void NonGenericMethod()
{
}
public void GenericMethod<V>(V parameter)
{
}
}
You need to use a concept call constraints ...
public class Gen<U> : IGen<U> where U : T
{
private U u;
public void Get<T>(ref T value)
{
if (value is U)
{
value = (T) u;
}
else
throw new Exception();
}
}
This tells you that U must be or derive from the argument supplied for T.
First, don't use ref for this either. Then your problem becomes moot.
public interface IThing
{
object Value { get; }
}
public interface IThing<T> : IThing
{
T Value { get; }
}
public class Thing<T> : IThing<T>
{
private T t;
public object Value
{
get
{
return this.Get();
}
}
public T Value<T>()
{
get
{
return this.t;
}
}
}
If you really want to accept some generic other, that is constrained to the right type
public interface ICrazyThing<T>
{
void Get<T>(ref T crazy);
}
public class CrazyThing<U, T> : IThing<T> where T : U
{
private U u;
public void Get<T>(ref T crazy)
{
crazy = this.u;
}
}
Even in crazy world, out would be a better choice than ref, since the value passed in is a pointless instantiation that has no bearing on the result.

How do I implement the service locator pattern with generic base classes?

I have gotten myself into a catch 22 and cannot seem to find my way out. I'm trying to implement a simple [Service Locator][1], represented by the GetInstance-method in the example code below. Now the problem is I get a compiler error on the return statement saying:
Cannot implicitly convert type 'Cyberspace.SubClass' to 'Cyberspace.BaseClass<T>'
I've tried rewriting so that the SubClass is a generic class itself, but then I get compiler error on the return statement in the DoSomething-method.
Can anyone make this code compile, retaining the Service Locator pattern principles which allow me to have an abstract return type in the GetInstace-method? Or am I trying to acheive something impossible here?
namespace Cyberspace
{
class BaseClass<T>
{
BaseClass<T> GetInstance()
{
return new SubClass();
}
virtual T DoSomething() { return default(T); }
}
class SubClass : BaseClass<OtherClass>
{
public override OtherClass DoSomething()
{
var other = new OtherClass { Description = "Generics are hard"};
return other;
}
}
class OtherClass
{
internal string Description { get; set; }
}
}
Attempt 2:
namespace Cyberspace
{
class BaseClass<T>
{
static BaseClass<T> GetInstance() // The "Service Locator" method
{
return new SubClass<T>();
}
internal virtual T DoSomething() { return default(T); }
}
class SubClass<T> : BaseClass<T> where T: OtherClass
{
internal override T DoSomething()
{
var other = new OtherClass { Description = "Generics are hard"};
return (T) other;
}
}
class OtherClass
{
internal string Description { get; set; }
}
}
This yields the following error on line return new SubClass<T>();
The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Cyberspace.SubClass<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'Cyberspace.OtherClass'
I'm unclear on what you're really trying to do, but I can tell you why that compile error is happening.
Anything that is returned from this method:
BaseClass<T> GetInstance()
Must be able to handle any type T (because you have no type constraints). SubClass can only handle one type, not all types. Therefore you can't return it.
When using a type parameter T you declare: "I don't care what the type actually is. I just need some type, any type at all. Call it T.". But in your case it looks like you want a specific type. No need for generics, then.
class SubClass : BaseClass<OtherClass>
{
internal override OtherClass DoSomething()
{
var other = new OtherClass { Description = "Generics are hard"};
return other;
}
}
Why doesn't the following work?
var other = new OtherClass { Description = "Generics are hard"};
return (T) other;
Because T might be derived from OtherClass. You cannot convert OtherClass to a class derived from OtherClass. Makes no sense and the compiler is smart enough to catch it.
The discussion in the comments lead to the following workaround:
return (BaseClass<T>)(object)new SubClass();
Of course, this only works, if the types line up at runtime.

C# Interfaces: Is it possible to refer to the type that implements the interface within the interface itself?

What I basically wish to do is design a generic interface that, when implemented, results in a class that can behave exactly like T, except that it has some additional functionality. Here is an example of what I'm talking about:
public interface ICoolInterface<T>
{
T Value { get; set; }
T DoSomethingCool();
}
public class CoolInt : ICoolInterface<int>
{
private int _value;
public CoolInt(int value)
{
_value = value;
}
public int Value
{
get { return _value; }
set { _value = value; }
}
public int DoSomethingCool()
{
return _value * _value;
// Ok, so that wasn't THAT cool
}
}
And this is all well and good, but in order to use CoolInt, I need to do something like this:
CoolInt myCoolInt = new CoolInt(5);
int myInt = myCoolInt.Value;
I'd much rather, in terms of assignment at least, that CoolInt works just like int. In other words:
CoolInt myCoolInt = 5;
int myInt = myCoolInt;
To achieve this, I added these two conversion operators to my CoolInt class:
public static implicit operator CoolInt(int val)
{
return new CoolInt(val);
}
public static implicit operator int(CoolInt obj)
{
return obj.Value;
}
Works awesomely. Now, I would prefer it if I could add these two overloads to the interface, so that implementers of the interface are forced to implement these operators. The problem is, the prototypes of these operators refer directly to CoolInt.
C# has a lot of "placeholder" names for things that are implicitly defined or have yet to be defined. The T that is conventionally used in generic programming is one example. I suppose the value keyword, used in Properties, is another. The "this" reference could be considered another. I am hoping that there's another symbol I can use in my interface to denote "the type of the class that is implementing this interface", e.g. "implementer".
public static implicit operator implementer(int val)
{
return new IntVal(val);
}
public static implicit operator int(implementer obj)
{
return obj.Value;
}
Is this possible?
Why don't you create an abstract class? This way you can build some "default" functionality into your class.
Sadly no :(
C# doesn't do well when it comes to operator overloading (This is one example, another is generic constraints on certain operator types).
Why not use extension methods instead? That lets you "add" methods to int without having to use a different type.
This is probably the closest you can get using an abstract base type, but sadly even this has an issue with one of the implicit operators and you have to do:-
CoolInt x = (CoolInt)5;
int j = x;
Close enough?
// Slightly sneaky, we pass both the wrapped class and the wrapping class as type parameters to the generic class
// allowing it to create instances of either as necessary.
public abstract class CoolClass<T, U>
where U : CoolClass<T, U>, new()
{
public T Value { get; private set; }
public abstract T DoSomethingCool();
// Non-public constructor
protected CoolClass()
{
}
public CoolClass(T value)
{
Value = value;
}
public static implicit operator CoolClass<T, U>(T val)
{
return new U() { Value = val};
}
public static implicit operator T(CoolClass<T, U> obj)
{
return obj.Value;
}
}
public class CoolInt : CoolClass<int, CoolInt>
{
public CoolInt()
{
}
public CoolInt(int val)
: base(val)
{
}
public override int DoSomethingCool()
{
return this.Value * this.Value; // Ok, so that wasn't THAT cool
}
}
It would be helpful if, at least for interfaces, one could declare that a class implements an interface in terms of an object; this would be especially cool if there was an "interface" generic type constraint. Then one could, for example, do something like (VB syntax)
Class Foo(Of T as Interface)
Implements T via Bar ' Declares variable 'bar' of type T
Sub DoSomething
' Does something
End Sub
End Class
and then cast a Foo(of T) to a T and have it behave like a T. Maybe someone from MS can stumble on the idea and pass it on?
I should note, btw, a nice pattern similar to your ICoolInterface:
public interface ISelf<T>
{
T Self { get;}
}
public interface IFoozle
{
... definitions for IFoozle
}
public interface IFoozle<T> : ISelf<T> , IFoozle;
{
/* Empty except for above declarations */
}
... similarly define IWoozle and IWoozle<T&gt etc.
Then one can declare a field which can implement IWoozle and IFoozle, and inherits from BoozleBase (which implements neither), via:
IWoozle<IFoozle<BoozleBase>> myField1;
or
IFoozle<IWoozle<BoozleBase>> myField2;
Note that the above two types can be cast to each other, or to types which also contain other interfaces. If one only needs to pass a variable meeting multiple constraints to a method, one can obtain such a thing more easily by using a generic method. Unfortunately, there's no way to store an object of unknown type in a field in such a way that it can be passed to a generic function with multiple constraints.

Categories

Resources