Join the Stack Overflow Community
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

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;
    }
}
share|improve this question
    
use overloading – kurakura88 3 hours ago
    
    
Why your priceLevels property has no setter? – S.Akbari 3 hours ago
    
Default Value by assignment for a function's input value can be the same as "const" assignment rules……So yours cannot be implemented directly until now. – DongWei 3 hours ago
    
@S.Akbari You're probably right. However, if the idea is to only allow priceLevels to be set on initialization (hence the default value as a fallback), then it's valid. – Michael McMullin 3 hours ago

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;
    }
}
share|improve this answer
1  
Also the priceLevels property should has setter. – S.Akbari 3 hours ago
    
Added a private setter. Thanks. – Ephraim 3 hours ago
    
If C# 6.0 the private set is unnecessary if the value is set in the constructor only. – Cubicle.Jockey 2 hours ago

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

But I think a better design all together would be to have 2 constructors 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;
    }
}

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;
    }
}
share|improve this answer
    
Also the priceLevels property should has setter. – S.Akbari 3 hours ago
    
@S.Akbari - Agreed. Updating – Gilad Green 3 hours ago
    
The null-coalescing operator on its own makes it 'better'! – Michael McMullin 3 hours ago
    
@MichaelMcMullin - haha :) true – Gilad Green 3 hours ago
    
Thanks, I think I will probably go with your final suggestion and re-think my structure. Also, curious about this setter thing... why is it necessary that I have a setter (even if it is private) if all I am doing is setting that value upon initialization of the class? – Adjit 3 hours ago

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)
    { }
}
share|improve this answer
    
@DongWei You surely can do it. Try it in linqpad. – Mathew 3 hours ago
    
:Sorry I should paste what I said to OP instead of you :) – DongWei 3 hours ago
1  
Liked this solution but you shouldn't make the newPriceLevels optional in one of the Constructors, that in my view has no benefit +1 – Mrinal Kamboj 3 hours ago

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;
  }
}
share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.