C# - 调用具有所有默认的参数结构构造函数(C# - Calling a struct const

2019-08-02 18:00发布

我今天在创建的时候就遇到了这个问题, 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;

但我的理念是,除非他们是私自使用领域conststatic

最后,我使用的理由struct ,而不是一class是因为这根本就是一个对象来保存非可变数据,它应该在建造时充分填充,当作为参数传递,不应该是能够被null (因为它是按值传递的struct ),这是什么结构的设计为。

Answer 1:

事实上,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代替。 如果我们在构造函数中设置它,这将为非空,并采取价值,而不是...



Answer 2:

我不认为这是很好的设计有一个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;
  }
}


Answer 3:

我猜编译器实际上是捡了自动默认构造函数的结构在这里http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx ,而不是使用您的构造函数使用默认值。

加入的引用: http://csharpindepth.com/Articles/General/Overloading.aspx (可选参数部分)



Answer 4:

虽然有些语言(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 ,但似乎相当做作。



Answer 5:

为什么你有public ExampleStruct(int value = 1) : this()

不应它是public ExampleStruct(int value = 1) 我认为:this()是创建无参数的构造函数。



文章来源: C# - Calling a struct constructor that has all defaulted parameters