Class 的 C# 可选数组参数

C# Optional Array Parameter for Class

我知道这可以使用 null 来完成,所以我有一个解决方法,但我想知道是否有更好的方法可以为 class?

class PriceLevels
{
    public int[] priceLevels { get; }
    private readonly int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

    public PriceLevels(int[] newPriceLevels = defaultPriceLevels)
    {
        priceLevels = newPriceLevels;
    }
}

这给了我一个错误,说它是一个无效的表达式 defaultPriceLevels 必须是常量。我该如何解决这个问题?

我能想到的一个解决方法是这个,但我不太喜欢这个解决方案

class PriceLevels
{
    public int[] priceLevels { get; }
    private readonly int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

    public PriceLevels(int[] newPriceLevels = null)
    {
        if(newPriceLevels == null) 
            priceLevels = defaultPriceLevels;
        else 
            priceLevels = newPriceLevels;
    }
}

一个更好的设计是让 2 个构造函数 (constructor overload) 一个获得 int[] 而另一个没有:

class PriceLevels
{
    public int[] priceLevels { get; set; }
    private readonly int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

    public PriceLevels()
    {
        priceLevels = defaultPriceLevels;
    }

    public PriceLevels(int[] newPriceLevels)
    {
       priceLevels = newPriceLevels;
    }
}

如果不是,不知道我是否会调用它 "better" 但你可以使用 params keyword:

class PriceLevels
{
    public int[] priceLevels { get; set; }
    private readonly int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

    public PriceLevels(params int[] newPriceLevels)
    {
        priceLevels = newPriceLevels.Length == 0 ? defaultPriceLevels : newPriceLevels;
    }
}

此外,根据设计,我不相信 PriceLevels 有责任决定默认值是什么,也许在任何情况下都应该将其作为依赖项 - 请参阅 SOLID and Dependency Injection。那么你只有 1 个构造函数:

class PriceLevels
{
    public int[] priceLevels { get; set; }

    public PriceLevels(int[] newPriceLevels)
    {
       priceLevels = newPriceLevels;
    }
}

您可以重载构造函数。

class PriceLevels
{
    public int[] priceLevels { get; private set; }
    private readonly int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

    public PriceLevels()
    {
        priceLevels = defaultPriceLevels;
    }

    public PriceLevels(int[] newPriceLevels)
    {
       priceLevels = newPriceLevels;
    }
}

您可以创建另一个不带参数的构造函数,它只会将您的 defaultPriceLevels 变量传递给您已有的构造函数吗?您也必须将变量更改为静态。

例如

class PriceLevels
{
    public int[] priceLevels { get; }
    private static int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

    public PriceLevels(int[] newPriceLevels = null)
    {
        if (newPriceLevels == null) priceLevels = defaultPriceLevels;
        else priceLevels = newPriceLevels;
    }

    public PriceLevels() : this(defaultPriceLevels)
    { }
}

只需创建构造函数的重载!一行代码真的可以轻松搞定!

public PriceLevels() : this(defaultPriceLevels) { }

然后,去掉原构造函数的默认参数值:

public PriceLevels(int[] newPriceLevels)

实际上,您还需要将defaultPriceLevels声明为static。希望你不介意。

C# 中不能使用可选的数组参数。来自 MSDN

Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used. A default value must be one of the following types of expressions:

  • a constant expression;
  • an expression of the form new ValType(), where ValType is a value type, such as an enum or a struct;
  • an expression of the form default(ValType), where ValType is a value type.

因此必须使用 "workaround"。检查 null(如您所建议的)或者您可以使用默认构造函数。

Crowd 中的另一个选项 :),最接近您的原始代码

class PriceLevels
{
  public int[] priceLevels { get; set; }

  private readonly int[] defaultPriceLevels = { 2, 3, 3, 4, 5, 6 };

  public PriceLevels(int[] newPriceLevels = null)
  {
     priceLevels = newPriceLevels ?? defaultPriceLevels;
  }
}