我今天在创建的时候就遇到了这个问题, struct
保存一组数据。 下面是一个例子:
public struct ExampleStruct
{
public int Value { get; private set; }
public ExampleStruct(int value = 1)
: this()
{
Value = value;
}
}
看起来很好,很正常。 问题是,当我尝试使用此构造而不指定值,并希望使用的1违约值的参数:
private static void Main(string[] args)
{
ExampleStruct example1 = new ExampleStruct();
Console.WriteLine(example1.Value);
}
该代码输出0
和不输出1
。 其原因是,所有的结构都有公共无参数的构造函数。 所以,就像我如何调用this()
我的显式构造,在Main
,会发生同样的事情,其中new ExampleStruct()
的实际调用ExampleStruct()
而不是调用ExampleStruct(int value = 1)
因为它确实是,它使用int
0的默认值Value
。
更糟糕的是,我的实际代码检查,看看是int value = 1
参数构造函数内的有效范围内。 将其添加到ExampleStruct(int value = 1)
以上的构造:
if(value < 1 || value > 3)
{
throw new ArgumentException("Value is out of range");
}
所以,它现在代表,默认构造函数实际上创建了一个对象,它是在我需要它的上下文无效。 任何人都知道我怎么可以:
- A.调用
ExampleStruct(int value = 1)
的构造。 - B.修改默认值是如何填充的
ExampleStruct()
构造函数。 - C.其他一些建议/选项。
另外,我知道我可以用一个领域像这样的,而不是我的Value
属性:
public readonly int Value;
但我的理念是,除非他们是私自使用领域const
或static
。
最后,我使用的理由struct
,而不是一class
是因为这根本就是一个对象来保存非可变数据,它应该在建造时充分填充,当作为参数传递,不应该是能够被null
(因为它是按值传递的struct
),这是什么结构的设计为。
事实上,MSDN有一些很好的指导struct
考虑定义的结构,而不是一类的,如果类型的实例是小的和通常短寿命或通常嵌入在其他对象。
不要定义一个结构,除非类型有以下所有特点:
它在逻辑上表示单个值,类似于原始类型(整数,双,和等等)。
它有一个实例大小大于16个字节小。
这是不可改变的。
它不会有频繁装箱。
请注意,他们是考虑考虑struct
,它决不是“这应该是一个结构”。 这是因为选择使用一个struct
可以有性能和使用情况的影响(正面和负面的),并应慎重选择。
特别注意,它们不推荐struct
的东西> 16个字节(然后复制的成本变得比复制基准更昂贵)。
现在,你的情况,确实做到这一点以外,以创建一个工厂产生一个没有什么好办法struct
为您在默认状态或做某种trick
在你的财产将其骗入初始化在第一次使用。
请记住,一个struct
应该工作,使得new X()
== default(X)
即新建struct
将包含该所有字段的默认值struct
。 这是非常明显的,因为C# 不会让你定义一个参数的构造函数的struct
,但奇怪的是,他们允许在没有警告是默认的所有参数。
因此,其实我建议你坚持使用一个class
,并使其不可变和只检查null
的,它被传递给方法。
public class ExampleClass
{
// have property expose the "default" if not yet set
public int Value { get; private set; }
// remove default, doesn't work
public ExampleStruct(int value)
{
Value = value;
}
}
但是 ,如果你绝对必须有一个struct
其他原因-但请考虑的成本struct
,如复制铸件,等等-你可以这样做:
public struct ExampleStruct
{
private int? _value;
// have property expose the "default" if not yet set
public int Value
{
get { return _value ?? 1; }
}
// remove default, doesn't work
public ExampleStruct(int value)
: this()
{
_value = value;
}
}
请注意,默认情况下, Nullable<int>
将是null
(即HasValue == false
),因此,如果这是真的,我们没有设置它,并且可以使用空合并运算符来回报广大的默认1
代替。 如果我们在构造函数中设置它,这将为非空,并采取价值,而不是...
我不认为这是很好的设计有一个struct
ExampleStruct
这样
default(ExampleStruct)
即所有实例字段都是零/假/空,是不是该结构的有效价值的价值。 如你所知,当你说
new ExampleStruct()
这是完全一样的default(ExampleStruct)
并为您提供了你的结构的值,其中所有字段(包括自动性“产生的”场)为零。
也许你可以这样做:
public struct ExampleStruct
{
readonly int valueMinusOne;
public int Value { get { return valueMinusOne + 1; } }
public ExampleStruct(int value)
{
valueMinusOne = value - 1;
}
}
我猜编译器实际上是捡了自动默认构造函数的结构在这里http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx ,而不是使用您的构造函数使用默认值。
加入的引用: http://csharpindepth.com/Articles/General/Overloading.aspx (可选参数部分)
虽然有些语言(CIL如果没有别的)会允许一个定义结构构造函数,使得new T()
具有设置为自己的“全零”默认,C#和vb.net(可能大多数其他语言)以外的其他领域采取认为,因为像数组元素和类字段必须始终被初始化为default(T)
并且由于具有它们被初始化为一些东西,不匹配new T()
将会引起混乱,结构不应该定义new T()
是指比其它东西default(T)
我建议,而不是试图去厄运的参数的构造函数默认参数,你只需定义它返回你想要的默认值为一个静态的结构特性,并更换的每次出现new ExampleStruct()
与ExampleStruct.NiceDefault;
。
2015年增编
看来,C#和VB.NET可以缓解对禁止定义参数的构造函数结构。 这可能会导致象语句Dim s = New StructType()
来分配s
的值是从给类型的新数组项的值不同StructType
。 我不是对变化非常敏锐的,因为new StructType
在地方一些类似于C#的经常使用default(StructType)
如果它存在会更合适。 VB.NET将允许Dim s As StructType = Nothing
,但似乎相当做作。
为什么你有public ExampleStruct(int value = 1) : this()
不应它是public ExampleStruct(int value = 1)
我认为:this()
是创建无参数的构造函数。