c# – 强制派生类来实现带有参数的基类构造函数

前端之家收集整理的这篇文章主要介绍了c# – 强制派生类来实现带有参数的基类构造函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
是否可以在需要实现构造函数(带参数)的派生类上执行编译时合约?

我有一个基类与构造函数需要一个参数:

public class FooBase
{
  protected int value;
  public FooBase(int value) { this.value = value; }
  public virtual void DoSomething() { throw new NotImplementedException(); }
}

我想强制派生我的基类实现相同的构造函数

public class Foo : FooBase
{
  public Foo(int value) : base(value) { }
  public override void DoSomething() { Console.WriteLine("Foo: {0}",value); }
}

如果没有实现构造函数,派生类将导致编译器错误,因为基类中没有默认构造函数

// ERROR: 'Does not contain a constructor that takes 0 arguments'
// Adding default constructor in FooBase eliminates this compiler error,but
// provides a means to instantiate the class without initializing the int value.
public class FooBar : FooBase
{
  public override void DoSomething() { Console.WriteLine("FooBar: {0}",value); }
}

在派生类中添加默认构造函数FooBar()会使编译器错误静默,但提供了一种实例化FooBar的危险方法,而不需要初始化所需的基类int值.因为我正在使用工厂(见下文),所以沉默编译器错误只会导致运行时错误.我想强制FooBar来实现FooBar(int)

兴趣观察:

如果一个默认构造函数FooBase()被添加到FooBase中,那么它不会由不提供构造函数的派生类继承:

> Foo不会继承默认构造函数,因为它提供了一个显式的构造函数.
> FooBar DOES继承FooBase().

然而,非默​​认构造函数FooBase(int)也是如此!

> Foo必须明确地实现FooBase(int)并调用base(int).
> FooBar FAILS以“继承”非默认构造函数的方式与继承默认构造函数的方式相同!

我不想要基类中的默认构造函数,因为实例是使用提供所需“设置”参数的工厂方法创建的.这里没有说明这种工厂方法(使用Activator.CreateInstance()方法).

这是派生类应该被实例化的方式:

static void Main(string[] args)
  {
    FooBase myFoo = new Foo(4);     // Works,since Foo(int) is implemented.

    // ERROR: 'Does not contain a constructor that takes 1 arguments'
    FooBase myFooBar = new FooBar(9);  // Fails to compile.
  }

因为我正在使用工厂 – 不是直接实例化,如图所示 – 没有编译错误.相反,我得到一个运行时异常:“未找到类型的构造方法”.

不可行的解决方

>接口不支持构造函数.
>构造函数不能是虚拟的或抽象的.

似乎提供基类不能强制执行构造函数的合同.

解决方法

>在基类中提供默认构造函数以及属性来传递设置参数.

解决方法

If a default constructor,FooBase(),
is added to FooBase,then it is
‘inherited’ by derived classes that do
not provide a constructor:

这是不正确的 – 构造函数通常不会继承.为不提供任何其他构造函数实现的类自动提供默认构造函数.

您可以在为您提供一个Init()方法的接口上加入约束:

public interface IInit
{
   void Init(int someValue);
}

public class FooBase : IInit
{
   ..
}

猜你在找的C#相关文章