C#接口的设计问题

时间:2011-07-27 11:13:30

标签: c# interface

我最近遇到了这样的困境:假设我想使用两个库,每个库都定义了一个消费者和消费品的接口:

#region Library A 
// This region represents a library (A) defining some interfaces

/// <summary>
/// Interface to be implemented by any processor of type A
/// </summary>
interface AProcessor
{
    void Process(AProcessable a);
}

/// <summary>
/// Interface to be implemented by any object processable by a processor of type A
/// </summary>
interface AProcessable
{
    int MyPropertyA { get; set; }
}
#endregion


#region Library B
// This region represents a library (B) defining some other interfaces

/// <summary>
/// Interface to be implemented by any processor of type B
/// </summary>
interface BProcessor
{
    void Process(BProcessable a);
}

/// <summary>
/// Interface to be implemented by any object processable by a processor of type B
/// </summary>
interface BProcessable
{
    int MyPropertyB { get; set; }
}
#endregion

然后,在我的应用程序中,我实现了一个消耗类型,它实现了每个库的两个可消耗接口:

/// <summary>
/// A type processable by processors of type A and processors of type B.
/// </summary>
class Processable :
    AProcessable,
    BProcessable
{
    // Implements interface AProcessable
    public int MyPropertyA { get; set; }

    // Implements interface BProcessable
    public int MyPropertyB { get; set; }
}

我实现了一个消费者类型,它能够使用Processable类型的对象,它实现了AProcessable和BProcessable:

/// <summary>
/// A processor that implements an A-type processor and a B-type processor.
/// </summary>
class Processor : 
    AProcessor, 
    BProcessor
{
    // I thought that Process method would implement AProcessor.Process() and
    // BProcessor.Process() as it expects a Processable object as parameter which
    // implements AProcessable and BProcessable, but it doesn't.
    // Compiler rises an error telling that Processor doesn't implement neither
    // AProcessor.Process() nor BProcessor.Process()
    /*
    public void Process(Processable a)
    {
        throw new NotImplementedException();
    }
    */


    // Implementing both methods does not work because it creates ambiguity: when
    // we call Processor.Process(p) being "p" a Processable object the compiler 
    // doesn't know if it has to call Processor.Process(AProcessable) or
    // Processor.Process(BProcessable).
    /*
    public void Process(AProcessable a)
    {
        throw new NotImplementedException();
    }

    public void Process(BProcessable a)
    {
        throw new NotImplementedException();
    }
    */
}

¿我的设计错误是什么?正确的方法是什么?

提前致谢。

5 个答案:

答案 0 :(得分:4)

您正在寻找显式接口实现。这个链接有一个教程:

http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

基本上,方法签名显示接口类型:

void BProcessor.Process(BProcessable b)
{

}

只能通过直接引用BProcessor

来访问
BProcessor b;
b.Process(null);

BProcessor的推断引用不适用于显式实现:

Processor p;
p.Process(new BProcessable()); // This won't compile.

这允许您实现具有冲突成员名称的接口。如果它们具有冲突的类型名称,则需要开始查看名称空间冲突。

您会注意到一个明确的实现,因为当您获得Processor的智能感知时,它将会丢失Process(BProcessable b)

如果您的处理流程代码恰好是共享的,您可以执行以下操作:

public void Process(Processable p)
{

}

void AProcess.Process(AProcessable a)
{
    Process((Processable)a);
}

void BProcess.Process(BProcessable b)
{
    Process((Processable)b);
}

但是,我个人会避免这种类型的正向投射,因为您无法保证(除了您完全控制代码之外)获得Processable类型。

答案 1 :(得分:2)

使用显式接口实现:

void AProcessor.Process(AProcessable a)
{
    throw new NotImplementedException();
}

void BProcessor.Process(BProcessable a)
{
    throw new NotImplementedException();
}

使用显式接口实现禁用自动查找要调用的方法。当您调用这些方法时,需要将对象强制转换为接口:

Processor p;
Processable pa;
((AProcess)p).Process(pa);

除了处理具有冲突名称/方法签名的这种情况之外,显式实现也可以用于隐藏(或者至少使其更难使用)接口所需的方法,但对于特定类没有意义

答案 2 :(得分:1)

我不认为这里需要显式接口实现,因为两种处理方法的签名之间没有冲突(参数的类型对于AProcessor是可处理的,对于第二种是BProcessable)。因为我想说,对于Processable实例,你希望两个处理都要执行,我会这样实现:

public class Processor : AProcessor, BProcessor
{
    #region AProcessor Members

    public void Process(AProcessable a)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    #endregion

    #region BProcessor Members

    public void Process(BProcessable a)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    #endregion

    public void Process(Processable a)
    {
        Process((AProcessable)a);
        Process((BProcessable)a);
    }
}

答案 3 :(得分:0)

在您的第一次尝试中,使用一种方法,您没有实现接口的精确定义,它不希望Processable对象作为参数,而是一个AProcessable和BProcessable,具体取决于您想要的那个。

正如其他人所指出的那样,第二个需要使用显式实现,以便您可以清楚地定义要调用的两个中的哪一个。

如果你想同时调用它们,那么你需要进行两次单独的调用 - 你可以在类中实现一个方法Process,并调用AProcessable.Process和BProcessable.Process。但它必须明确地完成,而不仅仅是通过继承和接口。

答案 4 :(得分:0)

每个人都提供了很好的解释,原因是代码不起作用的技术原因,但是我假设您理解这些,因为您的问题是设计问题是什么以及如何解决它...所以我会添加我的2c进入混合。

基本上你试图将两个完全不同的概念混合成一个逻辑控制代码(Processor类)。

通过定义可以处理的两个不同的东西,以及这些东西的处理器必须表现的两种方式,你正在设定定义一个以完全不同的方式处理两个不同事物的系统......因此它们不一样并且可以不能合并。

关于如何“解决”问题的另一个解决方案(我轻易使用单词fix,因为很难在不知道你解决的问题的上下文的情况下建议替代解决方案),你真的需要找到一种方法来表示两种可处理的类型和处理器以一种常见的方式......或者只是不将这两个概念混合在具体的处理器实现中。

了解问题的实际背景将有助于我们提供更准确的建议! :)

祝你好运!