Cast Generic instance to Base class - c#

I am trying to attempt something such as
void Main()
{
Temp<Bar> Test = new Foo<InheritedBar>();
}
abstract class Temp<T> where T : Bar
{
}
class Foo<T> : Temp<T> where T : Bar
{
}
abstract class Bar
{
}
class InheritedBar : Bar
{
}
The cast does not work, with the error Cannot implicity convert type Foo<InheritedBar> to Temp<Bar>.
However,
Temp<InheritedBar> Test = new Foo<InheritedBar>();
and
Temp<Bar> Test = new Foo<Bar>();
Both work. Why even though InheritedBar inherits from Bar, it can't be cast to it through generics?
I am using the generic type in a wpf Page, which can not be created as a generic so I can't pass T as its type. I only want the functionality at the time of this of Temp, not any of the derived versions functionality. Is there a better way to do this?

The concept you are attempting to utilize is covariance (full explanation on MSDN)
The short answer is that you need to use mark your generic parameter with out; but you can only do that on an interface (changing from an abstract class in your case). Also, depending on your method parameters and return values, you may not be able to mark your interface as covariant.
interface Temp<out T> where T : Bar
{
}

Related

.NET Core Cast to interface with generic type parameter of type which implements interface

In .NET Core C#
I' trying something like this:
(IInterface<IParameter>)instance
Where instance is new Implementation<Parameter>()
And Implementation : IInterface & Parameter : IParameter
The issue is with the casting of the generic parameter. When I provide Parameter instead of IParameter it works but at compile time there is no way to know which type that implements IParameter will be used. All of these objects will be created via reflection.
So is there any way this cast works? Or some other way to implement this like providing no generic type parameter like you can with typeof.
EDIT Thanks to Ziriax
A Fully Working Example:
interface IInterface
{
void Run(TInput input);
}
abstract class AbstractClass<TInput> : IInterface
where TInput : IParameter
{
public abstract void Execute(TInput input);
public void Run(IParameter input)
{
Execute((TInput)input);
}
}
interface IParameter {}
class Implementation : AbstractClass<Parameter>
{
public void Run(Parameter input)
{
}
}
class Parameter : IParameter {}
class Program
{
static void Main()
{
object instance = new Implementation();
var castInstance = (IInterface) instance;
castInstance.Run(new Parameter());
}
}
Why don't you add a non-generic interface too:
interface IInterface
{
void Run(IParameter input);
}
And then let your generic interface extend this non-generic one.
Obviously your implementations should cast the IParameter, someone needs to cast it... You could make an abstract base class that does this for you, so not every implementation has to do this.
You might also be interested in the double dispatch pattern, although I'm not sure this will work in your case.
As you have it now, this cannot work. Your Implementation class implements IInterface<Parameter>, so its Run method only accepts a parameter of the concrete Parameter type, whereas the IInterface<IParameter> requires that its Run method accepts an instance of any type that implements IParameter.
If the type of cast you're trying to do were allowed, I could define a different class that implements IParameter, e.g.:
public class DifferentParameter : IParameter { ... }
And then do:
castInstance.Run(new DifferentParameter());
But your Implementation's Run method can't take DifferentParameter!
.NET therefore prevents you from performing the cast itself.
There are situations in which this kind of cast is allowed - if your interface were instead to be defined as:
interface IInterface<out TOutput>
where TOutput : IResult
{
TOutput Run();
}
By making the generic parameter out, it makes the interface covariant. This restricts the use of the type parameter as the result of method calls, but for covariant interfaces, casts like yours are allowed.
You can find plenty of documentation on both covariance and contravariance in the .NET documentation.

Duck typing doesn't implicitly convert a type to an interface variable

public interface IInterface { }
public class MyClass { }
public static class Program {
public static void Main() {
IInterface myVariable = new MyClass();
}
}
I would expect this code to work since MyClass does satisfy IInterface, but I get a compilation error:
error CS0266: Cannot implicitly convert type `MyClass' to `IInterface'. An explicit conversion exists (are you missing a cast?)
Why?
Is there a workaround I can use that doesn't involve an explicit conversion?
Unfortunately, C# or .NET does not support duck typing in this particular context.
For a type to implement a particular interface, it will have to explicitly declare that it implements this interface. You say "satisfy" now, but this has no meaning for C# or .NET.
Does the type MyClass implement IInterface? No, sadly it doesn't.
This declaration:
public class MyClass { }
Declares a class that inherits System.Object, and does not implement any interface.
The fact that the interface contains no methods or properties does not in any way make it match up with this type. The class still does not implement this interface.
The only way for a class to implement an interface is to make it explicit:
public class MyClass : IInterface { }
So no, there is no way to force C# or .NET to consider that class as one implementing this interface.
The common ways to handle this is to make a wrapper class (ie. a class that implements IInterface and contains a MyClass, delegating all methods and/or properties to the contained MyClass instance), or, you know, actually implement the interface.
To conclude, the only way to make this code compile:
IInterface myVariable = new MyClass();
is to make MyClass explicitly either implement the interface:
class MyClass : IInterface { }
or to inherit from another class that implements it:
class BaseClass : IInterface { }
class MyClass : BaseClass { }

Using generics in interfaces in C#

I have an app written in C#. My app has a class that looks like the following:
public class FinderA
{
public IEnumerable<FinderA> GetItems()
{
return FinderA.FindAll();
}
}
I want to require other classes to do something similar. I cannot use a base class because my actual implementation is already using a base class. For that reason, I want to create an interface. Currently, I'm trying the following:
public interface IFinder
{
IEnumerable<T> GetItems();
}
When I use this approach, I get a compile-time error that says: "The type or namespace name 'T' could not be found (are you missing...". To overcome this, I add <T> to the end of the interface name so it looks like this:
public interface IFinder<T>
{
IEnumerable<T> GetItems();
}
This is turn generates another compile-time error that says: "Using the generic type 'IFinder' requires 1 type arguments.". My challenge is, I want the interface to be generic. I do not want to pass in a type. Is there a way around this? If so, what/how?
There is no way around this; you'll need to actually supply the generic type argument when declaring that a class implements the interface.
You can do this at the method level instead of as a generic type on the interface itself.
public interface IFinder
{
IEnumerable<T> GetItems<T>();
}
Your code can then call it like such:
IFinder finder = // Create finder instance
IEnumerable<MyClass> discoveredClasses = finder.GetItems<MyClass>();
If you want to ensure that MyClass is a class that implements IFinder, you can constrain the method.
public interface IFinder
{
IEnumerable<T> GetItems<T>() where T : IFinder;
}
That will cause the following to generate a compiler error:
public class Foo
{
}
public class Bar
{
Bar()
{
IFinder finder = // Create finder.
// This fails because <T> (Foo) does not implement IFinder.
IEnumerable<Foo> fooItems = finder.GetItems<Foo>();
}
}
but it will allow the following to compile
public class MyFinderA : IFinder
{
IEnumerable<T> GetItems<T>() where T : IFinder
{
return // Create collection of T
}
public class Bar
{
Bar()
{
IFinder finder = // Create finder.
// This works as <T> (MyFinderA) is an IFinder implementation
IEnumerable<MyFinderA> finderItems = finder.GetItems<MyFinderA>();
}
}
If you want your interface to be generic but you are not willing to supply a type argument, you can return an IEnumerable<object>.
public interface IFinder {
IEnumerable<object> GetItems();
}
All class types extend from System.Object so that should suffice for any type in your applicacion (enums and structs would get boxed)
Please note that this approach requires the interface's consumer to cast the generic object instances to the appropiate types.
The alternate (and recommended) approach is to make the interface use type parameters, but for that you must supply the appropiate type arguments

What's the point of having constraints for type parameters in .NET (base class and interface constraints)

I'm working on a small class library at work, and it naturally involves using generics for this task. But there is this thing that I don't really understand with generics:
Why would I need to use generic type parameters, and then constrain the the type parameter to a specific base class or interface.
Here's an example to what I mean:
public class MyGenericClass<T> where T : SomeBaseClass
{
private T data;
}
And here's the implementation without generics
public class MyClass
{
private SomeBaseClass data;
}
Are these two definitions the same (if yes, then i don't see the advatage of using generics here)?
If not, what do we benefit from using generics here?
As with almost all uses of generics, the benefit comes to the consumer. Constraining the type gives you the same advantages that you get by strongly typing your parameter (or you can do other things like ensure that there's a public parameterless constructor or ensure that it's either a value or reference type) while still retaining the niceties of generics for the consumer of your class or function.
Using generics also, for example, allows you to obtain the actual type that was specified, if that's of any particular value.
This example is a little contrived, but look at this:
public class BaseClass
{
public void FunctionYouNeed();
}
public class Derived : BaseClass
{
public void OtherFunction();
}
public class MyGenericClass<T> where T: BaseClass
{
public MyGenericClass(T wrappedValue)
{
WrappedValue = wrappedValue;
}
public T WrappedValue { get; set; }
public void Foo()
{
WrappedValue.FunctionYouNeed();
}
}
...
var MyGenericClass bar = new MyGenericClass<Derived>(new Derived());
bar.Foo();
bar.WrappedValue.OtherFunction();
The difference is that the former defines the new class as a specific type; the latter simply defines a plain class with a field of that type.
It's all about type safety. Using generics you can return a concrete type (T) instead of some base type which defines the API you need in your generic class. Therefore, the caller of your method won't have to cast the result to the concrete type (which is an error-prone operation).
The main difference is in usage. In the first case, the usage can have:
MyGenericClass<SomeDerivedClass> Variable
Variable.data.SomeDerivedProperty = X
And so that when you use that class, you can still access anything from SomeDerivedClass without casting back to it.
The second example will not allow this.
MyClass.data = SomeDerivedClassInstance
MyClass.data.SomeDerivedProperty = X //Compile Error
((SomeDerivedClass)MyClass.data).SomeDerivedProperty = X //Ewwwww
You will have to cast back up to the SomeDerivedClass (which is unsafe) to use something specific to the derived class.
I don't think that there is a huge amount of difference except that the generic version is constraining your Class, whereas the second is just a constraint on a member of the class. If you added more members and methods to your first Class, you would have the same constraint in place.

Casting generics and the generic type

Consider, I have the following 3 classes / interfaces:
class MyClass<T> { }
interface IMyInterface { }
class Derived : IMyInterface { }
And I want to be able to cast a MyClass<Derived> into a MyClass<IMyInterface> or visa-versa:
MyClass<Derived> a = new MyClass<Derived>();
MyClass<IMyInterface> b = (MyClass<IMyInterface>)a;
But I get compiler errors if I try:
Cannot convert type 'MyClass<Derived>' to 'MyClass<IMyInterface>'
I'm sure there is a very good reason why I cant do this, but I can't think of one.
As for why I want to do this - The scenario I'm imagining is one whereby you ideally want to work with an instance of MyClass<Derived> in order to avoid lots of nasty casts, however you need to pass your instance to an interface that accepts MyClass<IMyInterface>.
So my question is twofold:
Why can I not cast between these two types?
Is there any way of keeping the niceness of working with an instance of MyClass<Derived> while still being able to cast this into a MyClass<IMyInterface>?
This does not work because C# only supports covariance on the type parameters of interfaces and delegates. If your type parameter exists only in output positions (i.e. you only return instances of it from your class and don't accept it as an argument) you could create an interface like this:
interface IClass<out T> { }
class MyClass<T> : IClass<T> { }
Which would allow you to do this:
IClass<Derived> a = new MyClass<Derived>();
IClass<IMyInterface> b = a;
Honestly that is about as close as you are going to get and this requires the C# 4 compiler to work.
The reason you cannot do this in general is because most classes are not simple empty examples. They have methods:
class MyClass<T>
{
static T _storage;
public void DoSomethingWith(T obj)
{
_storage = obj;
}
}
interface IMyInterface { }
class Derived : IMyInterface { }
MyClass<Derived> a = new MyClass<Derived>();
Now, a has a method DoSomethingWith that accepts a Derived and stores it in a static variable of type Derived.
MyClass<IMyInterface> b = (MyClass<IMyInterface>)a;
If that was allowed, b would now appear to have a method DoSomethingWith that accepts anything that implements IMyInterface, and would then internally attempt to store it in a static variable of type Derived, because it's still really the same object referred to by a.
So now you'd have a variable of type Derived storing... who knows what.

Categories

Resources