提问人:Adjit 提问时间:10/11/2016 最后编辑:Gilad GreenAdjit 更新时间:9/21/2017 访问量:4542
类的 C# 可选数组参数
C# Optional Array Parameter for Class
问:
我知道这可以使用,所以我有一个解决方法,但我想知道是否有更好的方法可以为类提供可选参数?null
int[]
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;
}
}
答:
17赞
Gilad Green
10/11/2016
#1
一个更好的设计是有 2 个构造函数(构造函数重载),一个得到一个,另一个没有: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;
}
}
如果没有,不知道我是否会称其为“更好”,但您可以使用 params
关键字:
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;
}
}
此外,根据设计,我不相信决定默认值是什么是责任,也许它应该在任何情况下将其作为依赖项 - 请参阅 SOLID 和依赖项注入。那么你只有 1 个构造函数:PriceLevels
class PriceLevels
{
public int[] priceLevels { get; set; }
public PriceLevels(int[] newPriceLevels)
{
priceLevels = newPriceLevels;
}
}
评论
0赞
Salah Akbari
10/11/2016
此外,该物业应该有二传手。priceLevels
0赞
Michael McMullin
10/11/2016
null 合并运算符本身使它“更好”!
0赞
Adjit
10/11/2016
谢谢,我想我可能会接受你的最后建议并重新考虑我的结构。另外,对这个二传手的东西感到好奇......如果我所做的只是在类初始化时设置该值,为什么我必须有一个 setter(即使它是私有的)?
0赞
Gilad Green
10/11/2016
@Adjit - Cubicle.Jockey 在下面评论二传手。
0赞
Ivan Stoev
10/11/2016
@Gilad,我不认为第一部分有效 - 如果您称它为无参数,您仍然会收到空数组,而不是.params
null
9赞
jegtugado
10/11/2016
#2
您可以重载构造函数。
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;
}
}
评论
1赞
Salah Akbari
10/11/2016
此外,priceLevels 属性应具有 setter。
0赞
jegtugado
10/11/2016
添加了一个私人二传手。谢谢。
2赞
Cubicle.Jockey
10/11/2016
如果是 C# 6.0,则仅在构造函数中设置值时,私有集是不必要的。
7赞
Mathew
10/11/2016
#3
您可以创建另一个没有参数的构造函数,该构造函数只会将 defaultPriceLevels 变量传递给您已有的构造函数?您还必须将变量更改为 static。
例如:
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)
{ }
}
评论
0赞
Mathew
10/11/2016
@DongWei 你肯定能做到。在 linqpad 中试用。
0赞
xqMogvKW
10/11/2016
:对不起,我应该把我说的话贴给OP而不是你:)
1赞
Mrinal Kamboj
10/11/2016
喜欢这个解决方案,但你不应该在其中一个构造函数中使可选,在我看来,这没有好处+1newPriceLevels
4赞
Sweeper
10/11/2016
#4
只需创建构造函数的重载即可!只需一行代码即可轻松完成!
public PriceLevels() : this(defaultPriceLevels) { }
然后,从原始构造函数中删除默认参数值:
public PriceLevels(int[] newPriceLevels)
实际上,您还需要声明为 .希望你不介意。defaultPriceLevels
static
3赞
Ralf Bönning
10/11/2016
#5
可选的数组参数在 C# 中是不可实现的。来自 MSDN
每个可选参数都有一个默认值作为其定义的一部分。 如果未为该参数发送参数,则使用默认值。 默认值必须是以下类型的表达式之一:
- 一个恒定的表达式;
- 形式为 new ValType() 的表达式,其中 ValType 是一种值类型,例如枚举或结构;
- 表达式 窗体 default(ValType),其中 ValType 是值类型。
因此,必须使用“解决方法”。检查 null(如您建议的那样),也可以使用默认构造函数。
7赞
Mrinal Kamboj
10/11/2016
#6
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;
}
}
评论
priceLevels
priceLevels