通过引用传递:多个接口的子节点

时间:2011-03-17 19:04:56

标签: c# pass-by-reference multiple-inheritance

在将实现多个接口的对象传递给只需要其中一个接口的函数时,我遇到了构建错误。

我正在开发一个通讯包。 该软件包有一个Receiver类和一个Sender类。 Receiver类使用通知接口Receive_Notifier(函数对象)来处理通知。同样,Sender类使用通知接口Send_Notifier来处理通知。

interface Send_Notifier
{
    void sending_text(string text);
}

interface Receive_Notifier
{
    void raw_text_received(string raw_text);
}

class Sender
{
    Send_Notifier m_notifier = null;
    public Sender(ref Send_Notifier notifier)
    {
        m_notifier = notifier;
    }
    public void send(string text)
    {
        m_notifier.sending_text(text);
        return;
    }
}

class Receiver
{
    Receive_Notifier m_notifier = null;
    public Sender(ref Receive_Notifier notifier)
    {
        m_notifier = notifier;
    }
    public void receive(string text)
    {
        m_notifier.raw_text_received(text);
        return;
    }
}

我已将接口组合到Communications_Notifier中:

interface Communications_Notifier
    : Send_Notifier, Receive_Notifier
{
}

我创建了一个实现Notifier接口的Communications_Notifier类:

class Notifier
    : Communications_Notifier
{
    public void sending_text(string text)
    {
        System.Console.WriteLine("--> " + text);
    }
    public void raw_text_received(string raw_text)
    {
        System.Console.WriteLine("<-- " + raw_text);
    }
}

为了简化这篇文章,我只会展示发件人类:

class Sender
{
    Send_Notifier m_notifier = null;
    public Sender(ref Send_Notifier notifier)
    {
        m_notifier = notifier;
    }
    public void send(string text)
    {
        m_notifier.sending_text(text);
        return;
    }
}

问题是当我将Notifier的实例传递给Sender类的实例时:

class Program
{
    static void Main(string[] args)
    {
        Notifier the_notifier = new Notifier();
        Sender talker = new Sender(ref the_notifier); // ** Error generating line

        talker.send("Hello\n");

        string pause_text;
        pause_text = System.Console.ReadLine();
    }
}

Visual C#Express 2010中的错误:

Error   1   The best overloaded method match for 'Multiple_Inheritance_Interface.Sender.Sender(ref Multiple_Inheritance_Interface.Send_Notifier)' has some invalid arguments    C:\Users\Thomas\Programming_Experiments\C_Sharp\Multiple_Inheritance_Interface\Multiple_Inheritance_Interface\Program.cs    55  29  Multiple_Inheritance_Interface  
Error   2   Argument '1': cannot convert from 'ref Multiple_Inheritance_Interface.Notifier' to 'ref Multiple_Inheritance_Interface.Send_Notifier'   C:\Users\Thomas\Programming_Experiments\C_Sharp\Multiple_Inheritance_Interface\Multiple_Inheritance_Interface\Program.cs    55  44  Multiple_Inheritance_Interface

问题:

  1. Notifier为什么不能 转换为类型的引用 Sender,因为它实现了 Sender界面?
  2. 为什么要争论 构造函数无效?
  3. 注意:我正在从C ++,C和Java背景转换为C#。

2 个答案:

答案 0 :(得分:6)

ref参数不支持共同或反向差异。这是必要的,因为它可以读取和更改引用。因此,如果你传入一个派生类,并且该函数分配了一个不属于该派生类型的新实例,那么你的代码就会破坏。

示例:

void MakeCat(ref Animal animal)
{
  animal=new Cat();
}

Dog dog=new Dog();
MakeCat(ref dog);

这显然不起作用,因为现在您的Cat变量中有dog


我不确定你为什么首先使用ref。使用引用类型,您已经可以更改传入的实例的内容。您无法将传入的变量替换为该引用类型的新实例。


另一方面,

out参数看起来像是协变的。我怀疑它们不是由于运行时的限制:它们实际上是ref参数,标有一个属性,告诉编译器将其视为out参数。

答案 1 :(得分:4)

您滥用ref。在C#中,传统意义上只有struct是“按值传递”。默认情况下,对象引用传递给方法。例如:

class HypotheticalSender
{
    Send_Notifier m_notifier = null;

    public HypotheticalSender(Send_Notifier notifier) // no "ref"
    {
        m_notifier = notifier;
    }
}

// ...

HypotheticalSender talker = new HypotheticalSender(the_notifier);

the_notifier.InstanceProperty = "foobar";

// since talker's reference points to the same object, it sees "foobar" too

因此,构造函数中的ref关键字根本不需要。

这类似于Java的行为,与C和C ++的行为不同。