简体   繁体   English

如何在 C# 中为结构设置默认值?

[英]How to make a default value for the struct in C#?

I'm trying to make default value for my struct.我正在尝试为我的结构设置默认值。 For example default value for Int - 0, for DateTime - 1/1/0001 12:00:00 AM.例如 Int 的默认值 - 0,DateTime 的默认值 - 1/1/0001 12:00:00 AM。 As known we can't define parameterless constructor in structure.众所周知,我们不能在结构中定义无参数构造函数。

struct Test
{
    int num;
    string str;
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(default(Test)); // shows namespace and name of struct test.Test
        Console.WriteLine(new Test()); // same

        Console.ReadKey(true);
    }
}

How can I make a default value for struct?如何为结构设置默认值?

You can't.你不能。 Structures are always pre-zeroed, and there is no guarantee the constructor is ever called (eg new MyStruct[10] ).结构总是预先归零,并且不能保证构造函数会被调用(例如new MyStruct[10] )。 If you need default values other than zero, you need to use a class.如果您需要零以外的默认值,则需要使用类。 That's why you can't change the default constructor in the first place (until C# 6) - it never executes.这就是为什么您不能首先更改默认构造函数的原因(直到 C# 6) - 它永远不会执行。

The closest you can get is by using Nullable fields, and interpreting them to have some default value if they are null through a property:您可以获得的最接近的是使用Nullable字段,如果它们通过属性为 null,则将它们解释为具有一些默认值:

public struct MyStruct
{
  int? myInt;

  public int MyInt { get { return myInt ?? 42; } set { myInt = value; } }
}

myInt is still pre-zeroed, but you interpret the "zero" as your own default value (in this case, 42). myInt仍然预先归零,但您将“零”解释为您自己的默认值(在本例中为 42)。 Of course, this may be entirely unnecessary overhead :)当然,这可能完全是不必要的开销:)

As for the Console.WriteLine , it simply calls the virtual ToString .至于Console.WriteLine ,它只是调用虚拟ToString You can change it to return it whatever you want.您可以更改它以返回任何您想要的。

Your problem is not with the behaviour of C#/.Net.您的问题不在于 C#/.Net 的行为。 The way you instantiate the struct effectively creates an instance with default values for all member fields.您实例化结构的方式有效地为所有成员字段创建了一个具有默认值的实例。

The Console.WriteLine converts its argument to a string using the ToString() method. Console.WriteLine使用 ToString() 方法将其参数转换为字符串。 The default implementation ( Object.ToString() ) simply writes the fully qualified class name (namespace and name, as you call it).默认实现( Object.ToString() )只写完全限定的类名(命名空间和名称,如您所称)。

If you want another visualisation, you should override the ToString method:如果你想要另一个可视化,你应该覆盖ToString方法:

public struct Test
{
    int num;
    string str;
    public override string ToString()
    {
        return $"num: {num} - str: {str}";
    } 
}

Printing out objects of the C# results with namespaces unless you override .ToString() for your objects.除非您为您的对象覆盖 .ToString() ,否则使用命名空间打印出 C# 结果的对象。 Can you define your struct like below and try it ?你能像下面这样定义你的结构并尝试一下吗?

public struct Test
{
    int num;
    string str;
    public override string ToString()
    {
        return "Some string representation of this struct";
    }
}

PS: default(Test) gives you a struct contains default(int) and default(string) which I mean Test.num is 0 and Test.str is null PS:default(Test) 给你一个包含 default(int) 和 default(string) 的结构体,我的意思是 Test.num 是0而 Test.str 是null

Hope this helps希望这可以帮助

What you probably want to do is to override ToString() , eg您可能想要做的是覆盖ToString() ,例如

struct Test
{
    int num;
    string str;

    public override string ToString ()
    {
        return string.Format ($"{str} | {num}");
    }
}

As you have mentioned, it is impossible to define default values for fields other than default values for their appropriate types.正如您所提到的,除了为其适当类型的默认值之外,不可能为字段定义默认值。 However, with an overriden ToString() , you will see better formatted information about your structure in the console and during debugging.但是,使用覆盖的ToString() ,您将在控制台和调试期间看到有关您的结构的格式更好的信息。

This is my take on this in case somebody finds it useful.这是我对此的看法,以防有人发现它有用。

public struct MyStruct
{
    public int item1;
    public float item2;
    public float item3;

    public static MyStruct Null => new MyStruct(-1, 0, 0);
}

I have a static method inside my struct so that I can do this:我的结构中有一个静态方法,以便我可以这样做:

var data = MyStruct.Null;

instead of代替

var data = new MyStruct();
data.item1 = -1;
...

Or create a custom constructor to pass the data.或者创建一个自定义构造函数来传递数据。

You can also do this:你也可以这样做:

public struct MyStruct
{
    public static readonly Default = new MyStruct(42);

    public int i;

    public MyStruct(int i)
    {
        this.i = i;
    }
}

And then when you create a default struct of this type do this:然后当您创建这种类型的默认结构时,请执行以下操作:

public MyStruct newStruct = MyStruct.Default;

But of course, this won't override default and other programmers will bump their heads a few times.但是当然,这不会覆盖默认值,其他程序员会撞到他们的头几次。 Really consider if a struct is the way to go, from the microsoft docs :微软文档中真正考虑结构是否可行

"A structure type (or struct type) is a value type that can encapsulate data and related functionality. Typically, you use structure types to design small data-centric types that provide little or no behavior." “结构类型(或结构类型)是一种可以封装数据和相关功能的值类型。通常,您使用结构类型来设计提供很少或不提供行为的小型以数据为中心的类型。”

Consider this: if you had 2 values in your struct and you wanted to make constructors, would 2 or less constructors suffice?考虑一下:如果您的结构中有 2 个值并且您想创建构造函数,那么 2 个或更少的构造函数就足够了吗? If the answer is no, then the answer is: don't use a struct.如果答案是否定的,那么答案是:不要使用结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM