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

发布于 2024-10-22 06:06:36 字数 2992 浏览 3 评论 0原文

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

我正在开发一个通讯包。 该包有一个 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
{
}

我创建了一个实现 Communications_Notifier 接口的 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,因为它实现了 发送者接口?
  2. 为什么争论是 构造函数无效?

注意:我正在从 C++、C 和 Java 背景过渡到 C#。

I'm getting build errors when passing an object that implements multiple interface to a function that requires only one of the interfaces.

I'm developing a communication package.
The package has a Receiver class and a Sender Class. The Receiver class uses a notification interface Receive_Notifier (function object) for handling notifications. Likewise the Sender class uses a notification interface Send_Notifier to handling notifications.

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;
    }
}

I have combined the interfaces into a Communications_Notifier:

interface Communications_Notifier
    : Send_Notifier, Receive_Notifier
{
}

I created a Notifier class that implements the Communications_Notifier interface:

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);
    }
}

To simplify this post, I'll only show the sender class:

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;
    }
}

The issue is when I pass an instance of the Notifier to an instance of the Sender class:

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();
    }
}

The errors from 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

Questions:

  1. Why can't the Notifier be
    converted to a reference of type
    Sender, since it implements the
    Sender interface?
  2. Why is the argument to the
    constructor invalid?

Note: I'm transitioning from a C++, C and Java background to C#.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怪我入戏太深 2024-10-29 06:06:36

ref 参数不支持协变或逆变。这是必要的,因为它既可以读取也可以更改引用。因此,如果您传入派生类,并且该函数分配了一个不属于该派生类型的新实例,您的代码将会中断。

示例:

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

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

这显然行不通,因为现在您的 dog 变量中有一个 Cat


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


另一方面,out 参数看起来可能是协变的。我怀疑它们不是由于运行时的限制而导致的:它们实际上是用属性标记的 ref 参数,告诉编译器将其视为 out 参数。

ref parameters support no co- or contra-variance. This is necessary since it can both read and change the reference. So if you passed in a derived class, and the function assigned a new instance that's not of that derived type your code would break.

Example:

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

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

This obviously can't work since now you'd have a Cat in your dog variable.


I'm not sure why you're using ref in the first place. With reference types you already can change the content of the instance passed in. You just can't replace the variable passed in with a new instance of that reference type.


out parameters on the other hand look like they could be covariant. I suspect that they aren't is due to a limitation in the runtime: They are really ref parameters marked with an attribute telling the compiler to treat it as an out parameter.

对你再特殊 2024-10-29 06:06:36

您误用了 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++ 的行为不同。

You are misusing ref. In C#, only structs are "passed by value" in a traditional sense. By default, object references are passed to methods. For example:

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

So there's no need at all for the ref keyword in your constructor.

This is similar to Java's behavior, and dissimilar to C and C++'s behavior.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文