Lists of Generics Implementing an interface - c#

I've been reading C# newbie List<Interface> question and can understand why this first example works, but not the second. Why is the first good, but the second piece of code fails to compile.
First the good code:
interface IFoo {}
class Foo : IFoo { }
class Bar : IFoo { }
var list = new List<IFoo>();
list.Add(new Foo());
list.Add(new Bar());
Now for the code which introduces generics
interface IZar<TFoo> where TFoo : IFoo { }
class ZarFoo : IZar<Foo> { }
class ZarBar : IZar<Bar> { }
var list2 = new List<IZar<IFoo>>();
list2.Add(new ZarFoo());
list2.Add(new ZarBar());
This is failing to compile because ZarFoo cannot be converted to IZar when surely it should be able to as it implements IZar where Foo : IFoo?

Because IZar<TFoo> is not co-variant. You can't downcast the interface just like that.
You have to make IZar<TFoo> co-variant, by using out:
interface IZar<out TFoo> where TFoo : IFoo { }
The problem becomes clear when you create an add method:
interface IZar<TFoo> where TFoo : IFoo
{
void Add(TFoo foo);
}
class ZarFoo : IZar<Foo>
{
public void Add(Foo foo)
{ }
}
class ZarBar : IZar<Bar>
{
public void Add(Bar foo)
{ }
}
If you would use the interface, you could end up adding an IFoo, where the actual type is an Foo or Bar. Returning doesn't have that problem since IFoo can be either Foo or Bar. See, there is no inheritance problem:
interface IZar<out TFoo> where TFoo : IFoo
{
TFoo GetOne();
}
class ZarFoo : IZar<Foo>
{
public Foo GetOne()
{ return new Foo(); }
}
class ZarBar : IZar<Bar>
{
public Bar GetOne()
{ return new Bar(); }
}

Related

C#. Define a list of element of different generic type, but all with the same base type

I have the following structure:
public interface IFoo
{
}
public interface IFoo2 : IFoo
{
}
public interface IBar
{
}
public interface IQux<in TFoo, in TBar>
where TFoo : IFoo
where TBar : IBar
{
void Normalize(TFoo a, TBar b);
}
public interface IGamma : IQux<IFoo2, IBar>
{
}
public class Gamma : IGamma
{
public void Normalize(IFoo2 a, IBar b)
{
// do something with a and b
}
}
I have also:
a class that implements all the extensions of IFoo, that we can call FooImpl
a class that implements all the extensions of IBar, that we can call BarImpl
more extension of IQux where I define the type of the generics, like IGamma
Now, I want a list of IQux and call for each element the method Normalize with parameters an implementation of FooImpl and an implementation of BarImpl.
But if I define the list as follow and I use the method AddQux to add a new element to the list, I receive the following error:
Error CS1503 Argument 1: cannot convert from '<namespace>.IQux<TFoo, TBar>' to '<namespace>.IQux<<namespace>.IFoo, <namespace>.IBar>' in the instruction list.Add(c);
public class Builder
{
private IList<IQux<IFoo, IBar>> list = new List< IQux<IFoo, IBar> >();
public void AddQux<TFoo, TBar>(IQux<TFoo, TBar> qux)
where TFoo : IFoo
where TBar : IBar
{
list.Add(qux);
}
}
Any ideas on how it can be solved?

Enforcing generic interface childs type

I have a generic interface (MyInterface<T>), which is implemented by the class ChildA in the example below:
public interface MyInterface<T>
{
MyObj<T> GetObj(); // Irrelevant
}
class ChildA : MyInterface<ChildA>
{
// Irrelevant:
MyObj<ChildA> GetObj() {
return new MyObj<ChildA>();
}
}
This works, but I need to make sure that <T> always has the type of the implementing class, so in this case T should always be of type ChildA, because it is implemented by ChildA.
Another correct implementation could be this, for example:
class ChildB : MyInterface<ChildB> { ... }
But currently, this incorrect implementation is also possible, while it should not be:
class ChildA : MyInterface<ChildB> { ... }
Is there a way to enforce this?
You cannot enforce a generic type argument to be constrained to the implementing type.
The available type constraints are the following:
where T : struct
where T : class
where T : new()
where T : <base class name>
where T : <interface name>
where T : U
There is nothing like where T : self in C#. Actually, it wouldn't even make sense, because such a thing cannot be meaningfully enforced. Besides, it wouldn't fit at all into the covariance/contravariance concepts and would be weird to inherit from, in general.
The closest thing you can do is this:
public interface IMyInterface<T> where T : IMyInterface<T>
{
MyObj<T> GetObj();
}
Why it wouldn't make sense
Let's say you could do this:
public interface IMyInterface<T> where T : self // this syntax does not exist in C#
{
MyObj<T> GetObj();
}
Now all implementing types would have to use themselves as the type argument. But you could still do this:
public class ChildC<T> : IMyInterface<T> where T : self
{
/* ... */
}
Which would go around your restriction.
Is there a way to enforce this?
Well, not with generic constraints. You can do that with reflection though i'd vote against it :
public abstract class BaseChild<T> : MyInterface<T>
{
protected BaseChild()
{
if (typeof(T) != this.GetType())
{
throw new InvalidOperationException(string.Format(
"Type {0} is not supported as valid type parameter for type {1}",
typeof(T).Name, this.GetType().Name));
}
}
}
Example :
class ChildA : BaseChild<int> { }
// Bang! throws
var instance = new ChildA();
.
class ChildB : BaseChild<ChildB> { }
// Ok here
var instance = new ChildB();
You cannot do this but you can create your own control comparing the generic type of the interface and the type of your class. See the example:
class ChildA : MyInterface<ChildB>
{
public ChildA()
{
this.ValidateGenericType();
}
public MyObj<ChildB> GetObj()
{
return new MyObj<ChildB>();
}
protected void ValidateGenericType()
{
//throws an Exception because ChildB is different of ChilA
if (this.GetType().Name != this.GetType().GetInterfaces()[0].GetGenericArguments()[0].Name)
{
throw new Exception("The generic type must be of type ChildA.");
}
}
}
It seems that you should use extension methods instead of enforcing some interface for this purpose
public interface ISomeInterface {}
public class Child: ISomeInterface {}
public class OtherChild : ISomeInterface { }
public static class MyInterfaceExtensions
{
public static MyObj<T> GetMyObj<T>(this T child) where T : ISomeInterface
{
return new MyObj<T>();
}
}
public static class Test
{
public static void RunTest()
{
var child = new Child();
var otherChild = new OtherChild();
MyObj<Child> myObj = child.GetMyObj();
MyObj<OtherChild> myOtherObj = otherChild.GetMyObj();
}
}

Overloaded constructor passing the same reference multiple times

Lets say I have the following:
public interface IFoo
{
void Foo();
}
public interface IBar
{
void Bar();
}
public class FooAndBar : IFoo, IBar
{
//valid implementation
}
Now I have a class that takes in an IFoo and an IBar in the constructor, but has a paramter-less constructor as well.
public class Consumer
{
private IFoo foo;
private IBar bar;
public Consumer(IFoo foo, IBar bar)
{
this.foo = foo;
this.bar = bar;
}
public Consumer() : this(new FooAndBar(), new FooAndBar()) {}
}
I want to maintain the relationship between the paramter-less constructor calling the parameterized version. But I would like to pass in one referenced object rather than 'new'ing up two FooAndBar instances. Is there anyway to do this while still maintaining the relationship between the constructors?
You can create an interim private constructor that takes a FooAndBar as a parameter:
private Consumer(FooAndBar fooAndBar) : this(fooAndBar, fooAndBar) {}
public Consumer() : this(new FooAndBar()) {}

Two way reference with interfaces and generics

I've got a class with generics which uses another class, which in return needs to know what instance of the initial class "owns" it - which causes problems ;) Let me give an example:
public interface IFoo<T>
{
}
public interface IBar
{
IFoo<IBar> Foo { get; set; }
}
public class Foo<T> : IFoo<T> where T : IBar, new()
{
private readonly T _bar;
public Foo()
{
_bar = new T {Foo = this};
}
}
class Bar : IBar
{
public IFoo<IBar> Foo { get; set; }
}
This doesn't work as Foo = this doesn't work - even if I try to cast this to IFoo (compiles but fails at run time). I've tried to tweak the code various ways, but I've not found an implementation that works...
Hopefully you see what I'm trying to do, and perhaps you even see how I can achieve this ;-)
You can solve this with a combination of an explicit cast in the constructor, along with c#4.0 support for covariance on generic parameters.
First, you need to insert a cast in the Foo<T> constructor:
_bar = new T {Foo = (IFoo<IBar>)this};
Just doing that isn't sufficient, though. Your constraint that T : new() means that T needs to be a concrete class. As such, IFoo<T> will never be exactly IFoo<IBar>. However, if you specify that the generic parameter T for IBar<T> is covariant, then the cast from IFoo<Bar> to IFoo<IBar> will become legal:
public interface IFoo<out T>
The out keyword specifies that the parameter is covariant (which essentially means "this parameter will only be output by methods, never input.")
This MSDN article offers more details on covariance and contravariance.
Would declaring the T type parameter of IFoo as covariant solve your problem?
This code should allow you to do what you are trying:
public interface IFoo<out T> {
}
public interface IBar {
IFoo<IBar> Foo { get; set; }
}
public class Foo<T> : IFoo<T> where T : IBar, new() {
private readonly T _bar;
public Foo() {
_bar = new T { Foo = (IFoo<IBar>)this };
}
}
class Bar : IBar {
public IFoo<IBar> Foo { get; set; }
}
public static class Program {
public static void Main(params string[] args) {
Bar b = new Bar();
Foo<Bar> f = new Foo<Bar>();
}
}

Interface for method that returns its own type

I have a situation where i have a class
class Foo
{
Foo Bar()
{
return new Foo();
}
}
Now i wan tot create an interface for it
class IFoo
{
??? Bar();
}
What should be in place of the question marks? Each class should return it's own type, not Foo.
The solutions below work but do not looks clean. I don't understand why i have to specify the same class twice, and there is nothing like "this" for the current type
This is how i am using it later
class GenericClass<T> where T : IFoo
{
T foo = new T();
T item = foo.Bar();
}
You ask:
The solutions below work but do not looks clean. I don't understand why i have to specify the same class twice, and there is nothing like "this" for the current type
The reason why you have to specify it twice is because C# lacks the feature that you need.
What you want is something like this:
interface IFoo
{
IFoo Bar();
}
class Foo : IFoo
{
Foo Bar() // should work since Foo is an IFoo, but it's not supported by C#
{
return new Foo();
}
}
From a type-safety point of view, this should work (it's called return type covariance). In fact, other programming languages such as C++ or Java support this, see this example on Wikipedia. Unfortunately, return type covariance is not supported by C# (not even C# 4.0, which introduced covariance for generics), which is why you have to use the "generics workaround" illustrated in the other answers.
Covariant return types as well as a "this" type are proposed features for new versions of C#:
Champion "Covariant Return Types"
Proposal: support "type of the current object" as declared return type.
You could add a generic type and constrain it using the interface type:
public interface IFoo<T>
{
T Bar();
}
You'd implement this as follows:
public class Foo : IFoo<Foo>
{
public Foo Bar()
{
return new Foo();
}
}
public class Cheese : IFoo<Cheese>
{
public Cheese Bar()
{
return new Cheese();
}
}
Update, if you never care about the concrete return type of Foo, then you can do the following:
public interface IFoo
{
IFoo Bar();
}
Which is implemented like:
public class Foo : IFoo
{
public IFoo Bar()
{
return new Foo();
}
}
Then in your generic class:
public class GenericClass<T> where T : class, IFoo, new()
{
public T Rar()
{
T foo = new T();
T item = foo.Bar() as T;
return item;
}
}
GenericClass<Foo>.Rar(); will be a concrete implementation of Foo.
I think that the real question is: why you need the derived type in the interface? Interface is exactly for that reason - abstracting from the concrete classes. If it's just for convenience, so you don't have to cast to Foo after calling Bar(), you can implement the interface explicitly:
interface IFoo
{
IFoo Bar();
}
class Foo : IFoo
{
public Foo Bar()
{
return new Foo();
}
IFoo IFoo.Bar()
{
return Bar();
}
}
Ask yourself the question: why do you introduce an interface when you want the concrete type?
You can use an abstract base class plus explicit member implementation to achieve this. First, declare your interface like this:
interface IFoo
{
IFoo Bar();
}
Then, declare a generic abstract class that implements IFoo in an explicit manner, and also declares an abstract method that kind of "overloads" Bar(), but in a generic manner:
abstract class BaseFooImpl<T> : IFoo where T : BaseFooImpl
{
public abstract T Bar();
IFoo IFoo.Bar()
{
return Bar(); // this will call the abstract Bar()
}
}
Now, define your concrete classes like this:
class ConcreteFoo : BaseFooImpl<ConcreteFoo>
{
public override ConcreteFoo Bar()
{
return this; // for example, of course.
}
}
The advantage of this approach is that you can always use non-generic IFoo references to hold concrete instances. If you make your interface generic, you can't, for instance, declare these:
IFoo mammalInstance, fishInstance; // Instead of IFoo<Mammal> mammalInstance; IFoo<Fish> fishInstance;
List<IFoo> manyInstances; // Instead of List<IFoo<IFoo>>, which doesn't even work AFAIK
public interface IFoo<T>
{
T Bar();
}
Your implementation would then be:
class Foo : IFoo<Foo>
{
Foo Bar()
{
return new Foo();
}
}
class Baz : IFoo<Baz>
{
Baz Bar()
{
return new Baz();
}
}
You need to make the interface generic, like this:
interface IFoo<TClass> where TClass : IFoo<TClass>, class {
TClass Bar();
}
Not sure what you are trying to accomplish but it could be done this way:
interface IFoo<T>
{
T Bar();
}
class Foo:IFoo<Foo>
{
#region IFoo<Foo> Members
public Foo Bar()
{
return new Foo();
}
#endregion
}
Or Like this:
interface IFoo
{
IFoo Bar();
}
class Foo : IFoo
{
#region IFoo Members
public IFoo Bar()
{
return new Foo();
}
#endregion
}

Categories

Resources