是否可以将参数从派生类的默认构造函数传递给基构造函数

本文关键字:构造函数 默认 参数 派生 是否 | 更新日期: 2023-09-27 18:30:57

假设我有一个抽象的基类Deck:

public abstract class Deck
{
   public List<Card> cards;
   public Deck(string[] values, string[] suits)
   {...}
   ...
}

和一个派生类 EuchreDeck:

public class EuchreDeck : Deck
{
   string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
   string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };
   public EuchreDeck() : base(values, suits) // Error.
   {}
   ...
}

我希望能够实例化EuchreDeck并将两个字符串数组传递给基类,即 var gameDeck = new EuchreDeck(); .

目前我收到错误:"非静态字段、方法或属性EuchreDeck.values需要对象引用。

这是否可能,或者调用派生的默认构造函数将始终调用基默认构造函数?

是否可以将参数从派生类的默认构造函数传递给基构造函数

是的,如果你把数组static,你可以这样做:

public class EuchreDeck : Deck
{
   private static readonly string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
   private static readonly string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };
   public EuchreDeck() : base(values, suits)
   {
   }
}

不能像使用实例级成员那样使用它的原因是这样做是不合法的。这来自 C# 规范 10.10.1 构造函数初始值设定项,其中指出:

实例构造函数初始值设定项无法访问正在 创建。因此,在 构造函数初始值设定项的参数表达式,因为它是一个 参数表达式引用任何参数的编译时错误 通过简单名称的实例成员。

通过将数组切换为static,它们不再通过实例访问,而是通过EuchreDeck类型访问。


也就是说,我可能会建议您对设计进行轻微调整。也许使用工厂为您创建这些专用甲板,而不是它们的构造函数。

举个例子,也许重构这样的东西:

将基本Deck更改为仅取一组卡片:

public abstract class Deck
{
    public List<Card> Cards;
    protected Deck(IEnumerable<Card> cards)
    {
        this.Cards = new List<Card>(cards);
    }
}

然后像这样进行出厂设置:

public class EuchreDeck : Deck
{
    private EuchreDeck(IEnumerable<Card> cards) : base(cards)
    {
    }
    public class Factory : DeckFactory
    { 
        private static readonly string[] Values = new string[] { "9", "10", "J", "Q", "K", "A" };
        private static readonly string[] Suits = new string[] { "clubs", "spades", "hearts", "diamonds" };
        public static EuchreDeck Create()
        {
            var cards = CreateCards(Values, Suits);
            return new EuchreDeck(cards);
        }
    }
}

实例化/用法为:

EuchreDeck.Factory.Create();

您可以尝试工厂用法。我只是将其嵌套在类中,因此您无法使用无效的卡片集创建EuchreDeck。您的DeckFactory基将具有您的转换方法(看起来您当前在Deck构造函数中具有)

除此之外,我不确定您是否对EuchreDeck有特殊需求;我假设您还有其他与之相关的方法?如果没有,你可能会完全放弃这个类,让工厂创建一个带有所需卡片的Deck

我认为问题在于值和花色应该声明为静态的。

static string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
static string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

这样,它们将在实例化新类时可用。

你必须在某个地方贴花变量:

public EuchreDeck() : base(values, suits) // Error.
{}

在哪里申报valuessuits

您必须static定义它们,例如:

static readonly string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
static readonly string[] suits = new string[] 
              { "clubs", "spades", "hearts", "diamonds" }; 

问题是base(..)只能访问 ctor 范围内可见的值。因此,您不能传递实例变量,因为实例在该级别上无法访问,但您可以传递调用类的 ctor 参数静态成员