Casting interface type in Lazy<T> - c#

I want something like this:
public interface IAnimal
{ }
public class Dog : IAnimal
{
public Dog() {}
}
public class Cat : IAnimal
{
public Cat() {}
}
public abstract class TestClassBase
{
public TestClassBase()
{
_lazyAnimal = CreateLazyAnimal();
}
private Lazy<IAnimal> _lazyAnimal = null;
public IAnimal Animal
{
get
{
IAnimal animal = null;
if (_lazyAnimal != null)
animal = _lazyAnimal.Value;
return animal;
}
}
// Could be overridden to support other animals
public virtual Lazy<IAnimal> CreateLazyAnimal()
{
// default animal is a dog
return new Lazy<Dog>(); // this type of casting doesn't work and I don't know a good workground
}
}
I know from tinkering with MEF that it manages to find and store different types, implementing a single interface, into Lazy<T>. Just not sure how to do it myself.

Lazy<Dog> cannot be converted directly to Lazy<IAnimal>, but since Dog can be converted to IAnimal you can use the Lazy<IAnimal> constructor overload that expects an IAnimal (strictly speaking, it takes a Func that returns an IAnimal) and provide a Dog instead:
public virtual Lazy<IAnimal> CreateLazyAnimal()
{
// default animal is a dog
return new Lazy<IAnimal>(() => new Dog());
}

Casting Lazy<Dog> to Lazy<IAnimal> is not allowed because the types are different (the Lazy<T> type inherits just from object). In some cases, the casting can make sense - for example casting IEnuerable<Dog> to IEnumerable<IAnimal>, but the casting isn't safe in all cases.
C# 4.0 adds support for this casting in the safe case. It is called covariance and contravariance. For example, this article gives a nice overview.
Unfortunatelly, in C# 4.0 this works only for interfaces and delegates and not for concrete classes (e.g. Lazy<T>). You could probably solve the problem by creating interface ILazy<out T> and a wrapper for standard Lazy type, but it is probably easier to just write conversion from Lazy<Dog> to Lazy<IAnimal>.

Related

Declare an interface where concrete implementation has concrete types

public interface ISomeInterface
{
IOut SomeMethod(IIn aIn)
}
public class MyOut : IOut
{
public string AnExtraProp {get; set;}
}
public class MyIn : IIn
{
public string AnotherExtraProp {get; set;} }
}
public class MyConcreteOfSomeInterface : ISomeInterface
{
public MyOut SomeMethod(MyIn aIn)
{
}
}
Is it possible to have many classes (eg. MyConcreteOfSomeInterface, MyConcrete2OfSomeInterface, ....) implement an interface (eg. ISomeInterface) but yet have parameters of a concrete type (eg. MyIn, MyOut etc.).
I realise I could declare:
public interface ISomeInterface<TIn, TOut>
{
TOut SomeMethod(TIn aIn)
}
but as ISomeInterface will have many methods this will not be practical. So say I need to add additional methods SomeMethod2 and SomeMethod3 then I would end up with:
public interface ISomeInterface<TIn, TOut, TIn2, TOut2, TIn3, TOut3>
{
TOut SomeMethod(TIn aIn)
TOut2 SomeMethod(TIn2 aIn)
TOut3 SomeMethod(TIn3 aIn)
}
so the declaration becomes unwieldy pretty quickly.
What design pattern can I use to achieve:
Many concrete classes implementing an interface ISomeInterface AND
Using concrete parameters/return values that are implementing the necessary interfaces IIn, IOut?
There will be many methods on ISomeInteface with different types for the parameter/interface combos.
Let's simplify the problem. Suppose we have:
class Animal {}
class Giraffe : Animal {}
interface IFoo
{
Animal M();
}
Can we then have
class C : IFoo
{
public Giraffe M() => new Giraffe();
}
Unfortunately no. An interface implementation must match exactly.
Now, you might think "hey, the interface demands that an animal be returned, and I am returning an animal, namely, a giraffe, so what's the problem?"
The answer is that there is no problem. C# could have a type system where this works, and this feature has been proposed many many many times. It's called "return type covariance", and if you do a search here you'll find many questions about it.
However C# does NOT have this feature, and so you're out of luck. The best you can do is:
class C : IFoo
{
Animal IFoo.M() => this.M();
public Giraffe M() => new Giraffe();
}
And now you're good. The IFoo contract is explicitly implemented, and the public surface of the class has the more specific signature.
Similarly, what if we had:
interface IBar()
{
void N(Giraffe g);
}
This is not legal:
class D : IBar
{
public void N(Animal g) { ... }
}
Again, this would be perfectly sensible. IBar requires that D.N be a thing you can pass a giraffe to, and D.N is a thing that you can pass a giraffe or any animal to. But again, C# does not support this feature. This is called formal parameter contravariance and a very small number of programming languages support it.
Do a search on C# covariance and contravariance for details on what kinds of variance are supported by C#.
Also, note that this would not be typesafe:
interface IBaz
{
void P(Animal a);
}
class E : IBaz
{
public void P(Giraffe g) { }
}
Because you need to be able to say ((IBaz)(new E())).P(new Tiger()). IBaz says that an implementation must be able to accept any animal, so you cannot implement it with a method that only accepts giraffes. Logically it would be safe for return types to get more specific, but formal parameter types have to get less specific. That's why it's return type covariance but formal parameter type contravariance, because the direction of convertibility changes in the contra case.

How can a class inherit from a parameterized version of itself?

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

Returning the derived class instead of an interface

Is it possible to return the derived class in an interface definition in C#?
Some kind of return type covariance.
For example:
public interface IAnimal
{
this GetAnimal();
}
public class Dog : IAnimal
{
Dog GetAnimal() { return new Dog(); }
}
Is it possible to return the derived class in an interface definition
in C#?
Yes it is, if you define a generic interface.
public interface IAnimal<T>
{
T GetAnimal();
}
public class Dog : IAnimal<Dog>
{
public Dog GetAnimal() { return new Dog(); }
}
You could read further on this here.
C# doesn't support return type covariance, at least as of C# 6. It is a very commonly requested feature on the Roslyn GitHub, and was long before Roslyn even existed.
Eric Lippert wrote in his answer:
The feature is not implemented because no one here ever implemented it. A necessary but insufficient requirement is that the feature's benefits exceed its costs.
The costs are considerable. The feature is not supported natively by the runtime, it works directly against our goal to make C# versionable because it introduces yet another form of the brittle base class problem.
So sit back, hold tight, and cross your fingers for C# 7/8/9. But don't get your hopes up too much - as said, it's a high-cost low-benefit feature that would likely require modifications to the CLR.
For now, take a look at Christos' answer.
Sure if you pass the derived class as a type constraint :)
public interface IAnimal<T>
{
T GetAnimal();
}
public class Dog : IAnimal<Dog>
{
public Dog GetAnimal() { return new Dog(); }
}

casting to base interface implementation of reimplemented interface

I have an interface IFace implemented by class Animal. I cannot modify IFace or Animal. I want to extend Animal with my subclass Human and have it reimplement IFace. However, I want to be able to store an instance of Human in a variable of type IFace such that accessing that variable uses the Animal implementation directly—as if the variable’s type was Animal.
https://dotnetfiddle.net/6JjNfR
using System;
interface IFace
{
void Talk();
}
class Animal : IFace
{
public void Talk()
{
Console.WriteLine("Oink");
}
}
class Human : Animal, IFace
{
public new void Talk()
{
Console.WriteLine("Hi");
}
}
public class Program
{
public static void Main()
{
var human = new Human();
human.Talk();
var face = (IFace)human;
face.Talk();
var animal = (Animal)human;
animal.Talk();
var face2 = animal;
face2.Talk();
IFace face3;
face3 = human;
face3.Talk();
// How to get the following to oink like animal?
face3 = animal;
face3.Talk();
}
}
Is this possible or do I have to create a proxy class like the following?
https://dotnetfiddle.net/marXND
class AnimalProxy : IFace
{
Animal Animal { get; set; }
public AnimalProxy(Animal animal)
{
Animal = animal;
}
public void Talk()
{
Animal.Talk();
}
}
And if the proxy is required, why is the proxy required if I can access the Animal implementation of IFace by just casting to Animal?
I bet the answer has something to do with how explicit interfaces work and how casting a Human to an Animal and then again casting to IFace should return Human’s implementation… Maybe implicit interface implementation syntax just lets the C# compiler automatically generate an explicit implementation which just calls the implicit implementation. Which means that when I cast something to Animal I’m accessing Animal methods instead of IFace methods even though those same methods are the “implicit” implementation of IFace.
So, how can I cast directly to the base implementation of a reimplemented interface—and if that’s impossible, why?
Don't have the Human definition re-implement the interface:
class Human : Animal // , IFace
{
public new void Talk()
{
Console.WriteLine("Hi");
}
}
If you do that, the calling Talk on a Human will use the new implementation, but calling Talk on an IFace that happens to be a Human will use the base class' implementation.
See this article for some more informatoin, and even weirder circumstances, surrounding interface re-implementation.

Assignments using templates in c#

public class Animal
{
}
public class Cat : Animal
{
}
public class AnimalBag<T> where T : Animal
{
}
...
AnimalBag<Animal> bag = new AnimalBag<Cat>();
I get this error:
Cannot implicitly convert type AnimalBag<Cat> to `AnimalBag'
And if I try this:
AnimalBag<Animal> bag = (AnimalBag<Animal>) new AnimalBag<Cat>();
Cannot convert type AnimalBag<Cat> to AnimalBag<Animal>.
How can I resolve this kind of issues in C#? This works perfectly in Java.
The declaration AnimalBag<Animal> bag states that bag will be capable of storing any type of Animal. The assignment = new AnimalBag<Cat>(); contradicts this by saying that it is actually only capable of storing Cats. Which is it, as it cannot be both?
This case is where co-variant comes into play, but co-variant does not work with class, just only interface and delegate, so you need to define interface for co-variant using out keyword:
public interface IAnimalBag<out T> where T : Animal
{
}
public class AnimalBag<T> : IAnimalBag<T> where T: Animal
{
}
Then you can assign:
IAnimalBag<Animal> bag = new AnimalBag<Cat>();
You can check more co-variance and contra-variance in Generics

Categories

Resources