Two way reference with interfaces and generics - c#

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>();
}
}

Related

C# - Interface setting property to { get, set } another interface

So, I was writing two interfaces on the following structure:
public interface IBar
{
string DoStuff();
}
public interface IFoo
{
IBar Bar { get; set; }
}
On my implementation of IFoo, I have to do things like:
public class FooImpl : IFoo
{
private BarImpl _barImpl;
public IBar Bar
{
get { return _barImpl }
set { _barImpl = (BarImpl) value }
}
}
And then I will always have to be casting things around while using it, unless I manage some implicit operator which I don't want to.
So, is there a better way to write this in order to not cast things around and maybe have a clean Property { get; set; } on my implementations?
EDIT
Just to clarify why I (think) I need it this way: Let's say on my FooImpl I will need specific methods of BarImpl to work with. But DoStuff(), which are common to all IBars may be called from another places like fooImpl.Bar.DoStuff(). Does that make sense?
Thanks!
How about to use a generic interface? Try this code:
public interface IFoo<T> where T : IBar
{
T Bar { get; set; }
}
public class FooImpl : IFoo<BarImpl>
{
private BarImpl _barImpl;
public BarImpl Bar
{
get { return _barImpl; }
set { _barImpl = value; }
}
}
I think you're approaching the concept of Interfaces the wrong way. In absolute, IFoo shouldn't require a specific implementation of IBar. In your IFoo implementation, remove the any reference to BarImpl and replace it with IBar.
If, for an extraordinary reason, FooImpl can only work with BarImpl, and no other implementations, then in your IoC registrations just set it that way. Can't guide you through that if I don't know which IoC container you're using. If you're not using IoC at all, you can just instantiate the proper type of IBar of course.
You can have a constructor there which takes object of IBar type parameter and pass the BarImpl from outside the class which will add loose coupling to it like:
public class FooImpl : IFoo
{
private IBar _barImpl;
public IBar Bar
{
get { return _barImpl }
set { _barImpl = value; }
}
public FooImpl(IBar bar)
{
_barImpl = bar;
}
}
and in this case you would want to make your IBar property read only so that it's can't be changed from outside, so just add getter in it like:
public IBar Bar
{
get { return _barImpl; }
}
This way your FooImpl only knows about the interface and is not tightly bound with the implementation of the IBar and any implementation could be passed from outside.
Now when creating instance of FooImpl you will have to pass the BarImpl as parameter :
BarImpl bar = new BarImpl();
var foo = new FooImpl(bar);
Hope it helps!
One option is to use an explicit interface implementation:
public class FooImpl : IFoo
{
private BarImpl _barImpl;
public BarImpl Bar
{
get { return _barImpl; }
set { _barImpl = value; }
}
IBar IFoo.Bar
{
get { return _barImpl; }
set { _barImpl = (BarImpl)value; }
}
}
In this case, any time you are working with an object of type FooImpl, the Bar property will return a BarImpl type, removing the need to cast it in calling code. However, the class still implements IFoo properly and will return an IBar reference in any context where it is used as an IFoo reference.
This implementation becomes even cleaner if you can change IFoo.Bar to be read-only and instead require IFoo implementers to get their IBar member through a constructor or other means. This allows a FooImpl to require a BarImpl implementation of IBar without casting in the IFoo.Bar setter.

Delegate "wrong return type"

On one hand I have the following delegate :
public delegate IBar FooDelegate(string str);
public delegate IBar FooDelegateWithRef(string str, IBar someBar);
On the other hand I have a generic class :
public class MyBaseClass
where T : IBar, new()
{
public FooDelegate myFunc;
public FooDelegateWithRef myFuncWithRef;
}
public class MyClass<T> : MyBaseClass
where T : IBar, new()
{
public MyClass()
{
myFunc = Foo; //"Wrong return type"
myFuncWithRef = FooWithRef; //"No overload...matches delegate"
}
public T Foo(string){ ... }
public T FooWithRef(string, IBar){ ... }
}
My problem is when I do the following :
FooDelegate fooRef = MyClassInstance.Foo;
I get a 'wrong return type' error. I understand that a delegate signature must match the method signature, but since the "where" instruction in the generic actually specify clearly T is IBar, why doesn't it work ?
So two questions in one :
- why the compiler refuse to consider that the method signature is matching ?
- more importantly, how can I make this work ? I would prefer a delegate-friendly solution rather than using Func for conventions reasons.
note : I tried looking around for an answer, yet I might have the wrong wording for the question, so feel free to slap me in the face If this has been answered before.
EDIT : As #Jonathon Chase pointed out, my sample code doesn't quite wraps the problem. A non-working example can be found here. Edited the code above to reflect the issue.
EDIT 2 : All the answers where very informative to me, thanks a lot for your time. I would have checked all three if I could !
The "wrong return type" error is because variance does not support value types. So a class implementing IBar can be converted, while a struct implementing won't be:
class RefTypeBar : IBar {}
struct ValueTypeBar : IBar {}
FooDelegate f1 = new MyClass<RefTypeBar>().Foo; // This works
FooDelegate f2 = new MyClass<ValueTypeBar().Foo; // Fails - wrong return type
The error is generated inside of MyClass<T> because T could be a struct, so the complier can't guarantee that that Foo can be assigned a FooDelegate. If you add a class constraint to MyClass<T> the code will compile.
public class MyClass<T> : MyBaseClass where T : class, IBar, new()
There must be something else going on with your example here. I'm currently able to compile and run the following example and receive the expected result:
public class Program
{
public static void Main()
{
var x = new MyClass<Bar>();
FooDelegate test = x.Foo;
test("Do It");
}
public delegate IBar FooDelegate(string str);
public interface IBar { }
public class Bar : IBar { }
public class MyClass<T> where T : IBar, new()
{
T item;
public T Foo(string input) { Console.WriteLine(input); return item; }
}
}
DotNetFiddle
At least in your DotNetFiddle example, you can make the first assignment to funcA possible by changing the generic constraint to where T: Item, new().
In the second assignment, the delegate uses type T both as return type and as parameter type. I believe this leads to the sometimes strange effects of covariance and contravariance (MSDN about Co/Contravariance):
Let us assume that a generic instance uses a type class SubItem : Item {...}
for type parameter T of your class TypedFactory<T>.
It is ok to use SubItem as return type, since the return type will still be of (sub)type Item, and the delegate variable (e.g. funcA) still "satisfies" the contract described by the declaration of the delegate type.
But what happens if we used SubItem as a parameter type? The delegate variable (e.g. funcB) could no longer be called in each context which the declaration of the delegate type promises, e.g. Item blubb; factory.funcB("I am alive too", blubb) is not possible - the types do not match, since blubb is not of type SubItem. Since this might happen, the compiler has to complain here.
Maybe it is an option for you to make the delegates generic?
using System;
public interface IItem
{
string id {get;set;}
}
public class Item : IItem
{
public string id{get;set;}
}
public class BaseFactory<T>
where T: IItem, new()
{
public DelegateHolder.MakeWithID<T> funcA;
public DelegateHolder.MakeWithIDAndOther<T> funcB;
}
public class TypedFactory<T> : BaseFactory<T>
where T : IItem, new()
{
public TypedFactory()
{
funcA = makeNew;
funcB = makeNewFromOther;
}
public T makeNew(string itemId)
{
T _item = new T();
_item.id = itemId;
return _item;
}
public T makeNewFromOther(string itemId, T other)
{
T _item = new T();
_item.id = itemId;
return _item;
}
}
public class DelegateHolder
{
public delegate T MakeWithID<T>(string id) where T: IItem, new();
public delegate T MakeWithIDAndOther<T>(string id, T other) where T: IItem, new();
}
public class Program
{
public static void Main()
{
var x = new TypedFactory<Item>();
BaseFactory<Item> factory = x;
Item someItem = factory.funcA("I am alive");
Console.WriteLine(someItem.id);
Console.WriteLine(factory.funcB("I am alive too", someItem).id);
}
}

Is there any way an interface can cause different behavior?

Say I have the following code:
class Foo: IFoo {
public string fooProp { get; set; }
}
interface IFoo {
string fooProp {get; set; }
}
Is it at all possible for there to be different behavior between:
Foo x = new Foo();
someMethod(x);
and:
IFoo x = new Foo();
someMethod(x);
?
I think it may differ. If somebody's used bad style of programming, i.e.:
public void someMethod(IFoo f)
{
if (f is Foo)
{
Foo f1 = (Foo)f;
//Do smth with unique Foo members
}
//Do anything with IFoo members
}
Yes, there is a difference if someMethod has different overloads for IFoo and Foo.
public void someMethod(Foo f)
{
// Overload 1
}
public void someMethod(IFoo f)
{
// Overload 2
}
Foo x = new Foo();
someMethod(x); // Matches overload 1
IFoo x = new Foo();
someMethod(x); // Matches overload 2
(I'm no expert) but in your first scenario, you would get access to everything in Class Foo. In the second scenario, you would only be able to access the IFoo members. So if Foo has additional methods (that aren't part of the interface), you will be able to access them in your first scenario but not the second.
I believe using the interface name instead of the class name is just another way to encapsulate data and only provide access to the interface members. For instance you could have Foo and Bar which both implements IFoo. You could add both of them to, say, a List.
There would never be any difference.
Remember, an interface is a contract. By deriving Foo from IFoo, you are implementing that contract.
In both cases, because Foo is an IFoo and adheres to the contract, the behaviour will always be the same.
Of course, how Foo implements that contract is anybodies guess. But the contract is adhered too by the signature of the interface.
If you have two interfaces and there is a common method name in each of them then the implementing class can implement the same method differently. The it depends how the method is called - via interface or not and via which interface.
See here for a similar question:
Inheritance from multiple interfaces with the same method name
Different bahavior can be, but inside someMethod.
Say you have
class Foo: IFoo {
public fooProp { get; set; }
}
interface IFoo {
fooProp {get; set; }
myCustomProp {get;set}
}
if you have
public void someMethod(Foo _foo){
_foo.myCustomProp; //CAN DO THIS, AS YOUR TYPE IS _FOO_
}
Which will not be possible to do in case when the parameter of the method is defined like.
public void someMethod(IFoo _foo){
_foo.myCustomProp; //NO SUCH METHOD INFO
}
unless you don't cast. So the difference is that decaring IFoo, to decalre generic access parameter, but get less "potential" in terms of data access, but get a huge potential in abstraction over types in your architecture.
So the difference will be only in regard of architecture and program workflow.
You could have an explicitly implemented interface in Foo.
class Foo: IFoo {
private string _fooprop;
private string _ifooprop;
public string fooProp
{
get {return "IFoo";}
set {_fooprop=value;}
}
string IFoo.fooProp
{
get {return "Foo";}
set {_ifooprop=value;}
}
}
interface IFoo {
string fooProp {get; set; }
}
with this, you will have:
IFoo foo1=new Foo();
Foo foo2=new Foo();
Console.WriteLine(foo1.fooProp); // Foo
Console.WriteLine(foo2.fooProp); // iFoo
It's possible if you explicitly implement IFoo:
public class Foo : IFoo
{
public string Prop
{
get { return "Hello Foo"; }
}
string IFoo.Prop
{
get { return "Hello IFoo"; }
}
}
public static void SomeMethod<T>(T foo) where T : IFoo
{
var prop = typeof(T).GetProperty("Prop");
Console.WriteLine(prop.GetValue(foo));
}

Generic collection collision

Here's my best attempt to recreate the situation.
public interface IFoo
{
}
public class Foo : IFoo { }
public class Bar : IFoo { }
public class CollectionOf<T> : List<IFoo>
{
}
public class Bars : CollectionOf<Bar>
{
}
public class Test
{
public void Test()
{
CollectionOf<IFoo> bars = new Bars();
}
}
Compiler complains on the instantiation. Bars is a collection of IFoos. Is this one of those covariance/contravariance issues?
Yes.
Think about it for a second; bars should legally be able to hold objects of any type that implement IFoo. However, an object of type Bars can only hold objects of type Bar.
Using your code this would be allowed, which is obviously wrong.
CollectionOf<IFoo> bars = new Bars();
bars.Add( new Foo() ); // Uh oh!
That would effectively break the type safety afforded to you via generics.
Yes it is.
If this was allowed, you would be able to place any object into that collection, as long as it implemented the IFoo interface, but that wouldn't be safe for the collection.
Let me illustrate:
var b = new Bars();
CollectionOf<IFoo> bars = b;
bars.Add(Dummy); // implements IFoo, but does not descend from Bar
At this point, what does b contain? An object of type Dummy? That would be bad, and thus this is not allowed in the first place.
The fix, if there is one would depend on what it is that's not working for you. I can get your example to compile in two ways, either use IEnumerable or define your CollectionOf as an interface with the out generic modifier. Whether either is a fix for you I don't know:
public interface IFoo { }
public class Foo : IFoo { }
public class Bar : IFoo { }
public interface CollectionOf<out T> : IEnumerable<IFoo> { }
public class Bars : CollectionOf<Bar> { }
public class Test
{
public void Test()
{
IEnumerable<IFoo> bars1 = new Bars();
CollectionOf<IFoo> bars2 = new Bars();
}
}

Casting a non-generic type to a generic one

I've got this class:
class Foo {
public string Name { get; set; }
}
And this class
class Foo<T> : Foo {
public T Data { get; set; }
}
Here's what I want to do:
public Foo<T> GetSome() {
Foo foo = GetFoo();
Foo<T> foot = (Foo<T>)foo;
foot.Data = GetData<T>();
return foot;
}
What's the easiest way to convert Foo to Foo<T>? I can't cast directly InvalidCastException) and I don't want to copy each property manually (in my actual use case, there's more than one property) if I don't have to. Is a user-defined type conversion the way to go?
You can create an explicit conversion from Foo within Foo<T>.
class Program
{
static void Main()
{
Foo foo = new Foo();
foo.Name = "Blah";
Foo<int> newfoo = (Foo<int>)foo;
Console.WriteLine(newfoo.Name);
Console.Read();
}
}
class Foo
{
public string Name { get; set; }
public object Data { get; set; }
}
class Foo<T>
{
public string Name { get; set; }
public T Data { get; set; }
public static explicit operator Foo<T>(Foo foo)
{
Foo<T> newfoo = new Foo<T>();
newfoo.Name = foo.Name;
return newfoo;
}
}
Edit: This only works without inheritance. It appears you are not able to do a user-defined conversion from a base to a derived class. See comments from Mads Torgersen here http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/14cf27cf-b185-43d6-90db-734d2ca3c8d4/ :
We have taken the liberty of
predefining conversions (casts)
between base classes and derived
classes, and to make the semantics of
the language predictable we don't
allow you to mess with it.
It looks like you may be stuck with defining a method to turn a Foo into a Foo<T>. That, or drop the inheritance. Neither solution sounds particularly ideal.
If you are getting an InvalidCastException, the Foo type returned by GetFoo() is not Foo<T>. You will need to either pass T or typeof(T) to that function so it can return an instance of Foo<T>.
Use copy constructors. Foo implements:
class Foo {
Foo(Foo copy) { ... }
}
while Foo shall be constructed using the following:
class Bar<T> : Foo {
Bar(Foo copy) : base(copy) { ... }
}
...Yes. You need to copy member by member, and this should be done in "copy constructor".

Categories

Resources