C# Optional Array Parameter for Class

2019-04-04 07:10发布

I know this can be done using null so I have a workaround for that, but I was wondering if there was a better way that I can have an optional int[] parameter for a class?

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

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

This gives me an error saying it is an invalid expression defaultPriceLevels must be constant. How can I fix this?

One workaround that I can thing of is this, but I don't really like the solution

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;
    }
}

6条回答
时光不老,我们不散
2楼-- · 2019-04-04 08:00

You can overload your constructor.

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;
    }
}
查看更多
做个烂人
3楼-- · 2019-04-04 08:00

Just create an overload of the constructor! It can be really easily done with one line of code!

public PriceLevels() : this(defaultPriceLevels) { }

Then, remove the default parameter value from the original constructor:

public PriceLevels(int[] newPriceLevels)

Actually, you also need to declare defaultPriceLevels as static. Hopefully you don't mind that.

查看更多
beautiful°
4楼-- · 2019-04-04 08:05

A better design all together would be to have 2 constructors (constructor overload) one that gets a int[] and another that doesn't:

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;
    }
}

If not, don't know if i'd call this "better" but you can use the 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;
    }
}

Also, depending on design, I'm not convinced that it is PriceLevels responsibility to decide what the default values are and maybe it should get it as a dependency in any case - See SOLID and Dependency Injection. Then you'd have only 1 constructor:

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

    public PriceLevels(int[] newPriceLevels)
    {
       priceLevels = newPriceLevels;
    }
}
查看更多
淡お忘
5楼-- · 2019-04-04 08:07

Optional array parameters are not possible in C#. From 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.

Therefore a "workaround" has to be used. Either check for null (as you suggested) or you can use a default constructor.

查看更多
闹够了就滚
6楼-- · 2019-04-04 08:12

You could create another constructor with no parameters that would just pass your defaultPriceLevels variable to the constructor you already have? You'd have to change the variable to static too.

e.g.

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)
    { }
}
查看更多
疯言疯语
7楼-- · 2019-04-04 08:12

Another option in the Crowd :), which is closest to your original code

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;
  }
}
查看更多
登录 后发表回答