有人可以向我解释为什么在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";
}
}
}
这将产生编译错误:
错误参数1:无法从'NamespaceB.ClassB.ImpA'转换为'ref NamespaceA.ClassA.IInterfaceA'
想要修改接口属性并从foo()
调用接口函数似乎是完全合理的。如果您删除了ref
关键字,则会对其进行编译,但您在foo()
中所做的更改会丢失...
答案 0 :(得分:12)
正如Karthik所说,ref
和out
不支持面向对象的多态性。但是您可以使用泛型(a.k.a. 参数多态)来实现相同的效果。
尝试将foo
的签名更改为:
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);
}
答案 1 :(得分:0)
首先,无需在那里使用ref
关键字。
您正在将引用类型的实例作为参数传递,并且您不需要将参数标记为ref
以便能够修改其状态,此处为Property
属性。只需删除ref
关键字,它就会按预期工作。
其次,考虑一下。只要接口的实例是引用类型,ref
参数就可以更改传递的引用,因此理论上可以返回此接口的绝对不同的实现。
因此,明确地说,没有从IInterfaceA
到ImpA
的隐式强制转换,而您的代码需要一个。{/ p>