开发者

Passing by reference: child of multiple interfaces

开发者 https://www.devze.com 2023-02-18 00:41 出处:网络
I\'m getting build errors when passing an object that implements multiple interface to a function that requires only 开发者_JAVA技巧one of the interfaces.

I'm getting build errors when passing an object that implements multiple interface to a function that requires only 开发者_JAVA技巧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#.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号