gpt4 book ai didi

c# - 通用列表的接口(interface)继承

转载 作者:太空狗 更新时间:2023-10-29 21:17:17 28 4
gpt4 key购买 nike

我想为一个简单的项目构建一个生产者和消费者的通用系统。

我现在拥有的是

public interface IMessage     {    }
public interface Message1 : IMessage { }
public interface Message2 : IMessage { }
public interface IConsumer<T> { }
public interface IProducer<T> { }

public class Mop1 : IConsumer<Message1>, IProducer<Message2>
{
}



class Program
{
static void Main(string[] args)
{
var list = new List<IConsumer<IMessage>>();
var mop = new Mop1();
list.Add(mop); // Error occurs here
}
}

最后一行给出类似 cannot convert from 'Mop1' to 'IConsumer<GenericPubSub.IMessage>' 的错误

但是 Mop1 实现了一个 IMessage 派生类型的 IConsumer。这是一些方差问题吗?这有什么问题?

最佳答案

这是一个棘手的案例。您可以使用协变/逆变,但是...

我会稍微简化代码。只是为了关闭编译器,你可以这样做:

public interface IMessage { }

public interface Message1 : IMessage { }


public class Mop1 : IConsumer<Message1>
{
}

public interface IConsumer<out IMessage>
{
}


class Program
{
static void Main(string[] args)
{
var list = new List<IConsumer<IMessage>>();
var mop = new Mop1();

list.Add(mop); // Error occurs here
}
}

out IMessage将按照另一个答案中的建议进行操作,但它从根本上没有解决任何问题。让我展示一下,现在你想制作你的界面:

public interface IConsumer<out IMessage>
{
object Process (IMessage m);
}

aaa 它不会编译。因为简单地说,如果你说 out IMessage这意味着返回类型应该从 IMessage 派生,而不是参数类型。

所以你会这样:

public interface IConsumer<in IMessage>
{
object Process (IMessage m);
}

public class Mop1 : IConsumer<Message1>
{
public object Process (Message1 msg)
{
return null;
}
}

使其编译有效。但是现在你的 list.Add(mop);不管用。这是理所当然的,因为你的 Mop1确实不能转换为 IConsumer<IMessage>因为如果它是以下代码将是可能的:

list[0].Process (new Message2 ());

这是不可能的,因为 Mop1 只接受 Message1 .

所以回答这个问题。您实际上无法使用消息调度和纯 C# 编译器功能做任何有意义的事情。我知道它的发展方向,你想要静态类型的消息和东西。不幸的是,您不能拥有在通用列表中使用特定消息的消费者列表,您必须具有像 bool CanProcess(IMessage); IMessage Process(IMessage); 这样的抽象签名。并投在里面。您也可以使用自定义属性和反射稍微好一点,但同样,不能完全使用 C# 编译器。

关于c# - 通用列表的接口(interface)继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27510643/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com