【问题标题】:Passing implementations by ref: cannot convert from 'Foo' to 'ref IFoo' [duplicate]通过 ref 传递实现:无法从 'Foo' 转换为 'ref IFoo' [重复]
【发布时间】:2013-02-08 02:13:35
【问题描述】:

有人可以向我解释为什么这在 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 来操作对象的属性。
  • 必须同意@HighCore - 这里完全不需要 ref。
  • 我将标题从 reference 编辑为 ref。 C# 与 Java 和 Python 一样,使用 Call By Object Sharing 语义传递对象。这与 Call by Reference 无关(这是ref 所做的)。请参阅以前的 cmets。

标签: c# interface reference argument-passing


【解决方案1】:

正如 Karthik 所说,refout 不支持面向对象的多态性。但是您可以使用泛型(也称为 parametric 多态)来实现相同的效果。

尝试将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);
}

奖励 — 如果需要,您可以在类型参数 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();
}

【讨论】:

    【解决方案2】:

    首先,这里不需要使用ref关键字。

    您将引用类型的实例作为参数传递,并且不需要将参数标记为ref 即可修改其状态,此处为Property 属性。只需删除 ref 关键字,它就会按预期工作。

    其次,仔细想想。只要接口的实例是引用类型,ref 参数就可以更改传递的引用,因此理论上您可以返回该接口的完全不同的实现。

    因此,从 IInterfaceAImpA 的隐式转换绝对没有,而您的代码需要它。

    【讨论】:

      猜你喜欢
      • 2019-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      • 1970-01-01
      • 2012-09-16
      相关资源
      最近更新 更多