通过ref传递实现:无法从';Foo';到';参考IFoo';
本文关键字:Foo IFoo 参考 ref 实现 通过 | 更新日期: 2023-09-27 17:58:20
有人能向我解释为什么这在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()
中所做的更改将丢失。。。
ref
和out
不支持面向对象的多态性。但是你可以使用泛型(又称参数多态性)来达到同样的效果。
尝试将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);
}
Bonus-如果您愿意,您可以在类型参数T
上设置new()
约束,然后它甚至允许您调用其默认构造函数:
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();
}
首先,这里不需要使用ref
关键字。
您将引用类型的实例作为参数传递,并且不需要将该参数标记为ref
即可修改其状态,此处为Property
属性。只需删除ref
关键字,它就会按预期工作。
第二,好好想想。一旦接口的实例是引用类型,ref
参数就可以更改传递的引用,因此理论上可以返回该接口的完全不同的实现。
因此,毫无疑问,从IInterfaceA
到ImpA
没有隐式转换,而您的代码需要一个。