可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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;
}
}
回答1:
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;
}
}
回答2:
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:
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)
{ }
}
回答4:
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;
}
}
回答5:
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.
回答6:
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.