C#功能参数实现抽象类和多个接口

时间:2014-02-04 09:53:50

标签: c# interface parameter-passing multiple-inheritance abstract

考虑C#中的以下结构:

interface I1
interface I2

abstract class A
- class A1 : A
  - class A11 : A1, I1
  - class A12 : A1, I2
- class A2 : A
  - class A21 : A2, I1
  - class A22 : A2, I2

现在我有一个B类,它在构造函数中接受一个参数。该参数必须是以某种方式从A派生并实现接口I2的类,即它可以是类型A12或A22,但不是A11或A21。我该如何定义该参数?此外,我想稍后将参数存储为B中的属性(以供以后使用)。

我无法将A重新定义为接口,因为它提供了许多虚拟方法。我也不能跳过树状继承方案,因为A1和A2提供了许多在别处使用的特定方法(不在B中)。所以,我需要在B中处理的是来自A和I2的东西。

3 个答案:

答案 0 :(得分:5)

这对你有用吗?

class B<T> where T : A, I2
{
    public B(T parameter)
    {
        this.Property = parameter;
    }

    public T Property { get; private set; }
}

答案 1 :(得分:5)

  

如何定义该参数?

基本上,你不能。不在构造函数中。

你最接近的是创建一个返回B的静态泛型方法:

public static B CreateInstance<T>(T item) where T : A, I2

您不能在构造函数中执行此操作,因为构造函数不能是通用的。

但是,如果您需要存储该值,则需要选择包含AI2类型的字段,并在需要时进行投射

当然,根据Enigmativity的回答,您可以使B通用 - 但这可能会在其他地方产生其他影响。如果您想要非通用B,则可能同时拥有两者:

public abstract class B
{
    // Common operations which don't depend on the constructor parameter
}

public class B<T> : B where T : A, I2
{
    public B(T item)
    {
    }
}

当然,这开始变得相当复杂。

或者,您可以跳过编译时检查,并在执行时检查:

public class B
{
    private readonly A item;

    public B(A item)
    {
        if (!(item is I2))
        {
            throw new ArgumentException("...");
        }
        this.item = item;
    }
}

虽然编译时安全性通常是优选的,但它可能在这种情况下你不需要经历额外的箍。这实际上取决于你对这种类型做了什么。

答案 2 :(得分:0)

您是否需要创建A1,A2,A12,A22类的实例,如果没有,那么您可以将它们抽象化并仅限制实现它们的类的构造函数参数

class B
    {
        public B(A11 a12)
        {

        }

        public B(A22 a12)
        {

        }   

    }