Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing implementations by ref: cannot convert from 'Foo' to 'ref IFoo' [duplicate]

Can someone explain to me why this is incorrect in C#:

namespace NamespaceA
{
    public class ClassA
    {
        public interface IInterfaceA
        {
            String Property
            {
                set;
            }
        }
    }
}

namespace NamespaceB
{
    public class ClassB
    {
        public class ImpA: NamespaceA.ClassA.IInterfaceA
        {
            private String mProperty;
            public String Property{ set{ mProperty = value; } }
        }
        public ClassB()
        {
            ImpA aImpA = new ImpA();
            foo(ref aImpA);
        }

        private void foo(ref NamespaceA.ClassA.IInterfaceA aIInterfaceA)
        {
            aIInterfaceA.Property = "SomeValue";
        }
    }
}

This will produce a compile error of:

Error Argument 1: cannot convert from 'NamespaceB.ClassB.ImpA' to 'ref NamespaceA.ClassA.IInterfaceA'

It seems perfectly reasonable to want to modify the interface properties and call the interface functions from foo(). If you remove the ref keyword, it compiles, but the changes you make in foo() are lost...

like image 225
JHowIX Avatar asked Feb 08 '13 02:02

JHowIX


1 Answers

As Karthik said, ref and out don't support object-oriented polymorphism. But you can use generics (a.k.a. parametric polymorphism) to achieve the same effect.

Try changing the signature of foo to:

private void foo<T>(ref T aIInterfaceA) 
    where T : NamespaceA.ClassA.IInterfaceA
{
    aIInterfaceA.Property = "SomeValue";

    // This assignment will be visible to the caller of foo
    aIInterfaceA = default(T);
}

Bonus — If you want, you can put a new() constraint on the type parameter T and then it even lets you call its default constructor:

private void foo<T>(ref T aIInterfaceA) 
    where T : NamespaceA.ClassA.IInterfaceA, new()
{
    aIInterfaceA.Property = "SomeValue";

    // This assignment will be visible to the caller of foo
    aIInterfaceA = new T();
}
like image 141
Saintali Avatar answered Nov 05 '22 13:11

Saintali