17

是否可以设置或覆盖结构的默认状态?

例如,我有一个

enum something{a,b,c,d,e};

以及链接该枚举的 2 个值的结构

struct SomethingData
{
    something type;
    int Value;
    double Multipler;

    SomethingData(something enumVal, int intVal, double DblVal) {...}
}

但是我可以指定默认状态是

SomethingData(something.c,0,1);
4

12 回答 12

13

结构构造函数与类构造函数类似,但有以下区别:

结构不能包含显式的无参数构造函数。结构成员会自动初始化为其默认值。结构不能具有以下形式的初始值设定项:base (argument-list)。

http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx

所以,简短的回答,不,你不能覆盖默认构造函数(每个结构都有一个无参数的构造函数,你不能隐藏它或覆盖它)......

于 2010-12-21T17:17:55.777 回答
8

你不能。结构总是有一个默认构造函数,它将每个成员设置为其默认值(null对于引用类型、0数字类型、false布尔值等)。这种行为无法更改。

于 2010-12-21T17:19:29.670 回答
1

您不能覆盖结构的默认(无参数)构造函数。您只能添加带有参数的新构造函数。

http://csharp.2000things.com/2010/10/03/108-defining-a-constructor-for-a-struct/

于 2010-12-21T17:30:21.223 回答
1

创建一个类对象将导致所有实例字段在任何东西——甚至类构造函数——可以访问它之前就已经存在,并且分配一个数组将导致它的所有元素在任何东西可以访问该数组之前就存在。这两个动作都会导致分配给这些字段或元素的所有内存都清零,而不考虑要存储在其中的数据类型

当一个类类型的存储位置出现时,它最初会持有一个空引用。当结构类型的存储位置出现时,它的所有字段(以及其中的任何结构字段)将同时进行。与只能通过使用构造函数才能存在的类对象实例不同,结构类型存储位置的存在无需使用任何结构自己的代码。因此,结构的定义对于“实例”[即结构类型的存储位置]出现时应该发生什么没有发言权。

从根本上说,结构是用胶带绑定在一起的字段的集合。如果一个结构应该表现得像其他东西,它通常应该使其字段私有并假装是不可变的[即使结构赋值实际上通过用源中的相应值覆盖其所有字段来改变目标结构,以及结构定义在这件事上没有发言权]。然而,如果一个结构应该封装一组固定的相关但独立的值(例如,一个点的坐标),它可以独立地容纳对其各自类型合法的任何值组合,一个结构应该简单地公开它的字段。有些人可能会抱怨“可变结构是邪恶的”,但邪恶只适用于在结构上调用自变异方法时。将其状态作为字段公开的结构的行为类似于用胶带粘在一起的变量集合。如果一个人需要的是一组用胶带粘在一起的变量,那么试图让一个结构假装是不可变的只会让编程变得更加困难。

于 2013-05-23T22:22:41.187 回答
1

有一种解决方法可以通过使用自定义属性 getter 来实现这一点。观察:

public struct Foostruct
{
    private int? _x;
    private int? _y;

    public int X
    {
        get { return _x ?? 20; } // replace 20 with desired default value
        set { _x = value; }
    }

    public int Y
    {
        get { return _y ?? 10; } // replace 10 with desired default value
        set { _y = value; }
    }
}

这仅适用于值类型(可以用 nullable 包装),但您可以通过将引用类型包装在如下的泛型类中来对引用类型执行类似的操作:

public class Wrapper<TValue>
{
    public TValue Value { get; set; }
}

public struct Foostruct
{
    private Wrapper<Tick> _tick;

    public Tick Tick
    {
        get { return _tick == null ? new Tick(20) : _tick.Value; }
        set { _tick = new Wrapper<Tick> { Value = value }; }
    }
}
于 2016-11-21T01:33:17.827 回答
0

有点相关:我经常想将新的对象初始化器语法与不可变值类型一起使用。但是,鉴于典型的不可变值类型实现的性质,无法使用该语法,因为属性是只读的。

我想出了这种方法;在我看来,这仍然满足值类型的不变性,但允许负责实例化值类型的代码更好地控制内部数据的初始化。

struct ImmutableValueType
{
    private int _ID;
    private string _Name;

    public int ID
    {
        get { return _ID; }
    }

    public string Name
    {
        get { return _Name; }
    }

    // Infuser struct defined within the ImmutableValueType struct so that it has access to private fields
    public struct Infuser
    {
        private ImmutableValueType _Item;

        // write-only properties provide the complement to the read-only properties of the immutable value type
        public int ID
        {
            set { _Item._ID = value; }
        }

        public string Name
        {
            set { _Item._Name = value; }
        }

        public ImmutableValueType Produce()
        {
            return this._Item;
        }

        public void Reset(ImmutableValueType item)
        {
            this._Item = item;
        }

        public void Reset()
        {
            this._Item = new ImmutableValueType();
        }

        public static implicit operator ImmutableValueType(Infuser infuser)
        {
            return infuser.Produce();
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        // use of object initializer syntax made possible by the Infuser type
        var item = new ImmutableValueType.Infuser
        {
            ID = 123,
            Name = "ABC",
        }.Produce();

        Console.WriteLine("ID={0}, Name={1}", item.ID, item.Name);
    }
}
于 2010-12-21T18:55:02.563 回答
0

每次获取/设置属性时,都需要设置默认值调用 InitDefaultValues() 方法

private string _numberDecimalSeparator;
public string NumberDecimalSeparator
{
    get
    {
        InitDefaultValues();
        return _numberDecimalSeparator;
    }
    set
    {
        InitDefaultValues(); 
        _numberDecimalSeparator = value;
    }
}

...

private void InitDefaultValues()
{
    if (!_inited)
    {
        _inited = false;
        var ci = CultureInfo.CurrentCulture;
         _numberDecimalSeparator = ci.With(x => x.NumberFormat).Return(x => x.NumberDecimalSeparator, ".");

        ...
    }
}
于 2013-06-09T16:56:32.943 回答
0

有点愚蠢,但有效

public readonly static float default_value = 1;
public struct YourStruct{

    public float yourValue{
        get {
            return _yourValue + default_value;
        }
        set {
            _yourValue= value - default_value;
        }
    }
    public float _yourValue;
}
于 2016-01-13T17:32:37.393 回答
0

我的解决方案。它也有效。

public struct DisplayOptions
{
    public bool isUpon;
    public bool screenFade;

    public static DisplayOptions Build()
    {
        // Return default value
        return new DisplayOptions(true, true);
    }

    DisplayOptions(bool isUpon, bool screenFade)
    {
        this.isUpon = isUpon;
        this.screenFade = screenFade;
    }

    public DisplayOptions SetUpon(bool upon)
    {
        this.isUpon = upon;
        return this;
    }

    public DisplayOptions SetScreenFade(bool screenFade)
    {
        this.screenFade = screenFade;
        return this;
    }
}

使用默认值

        // Use default
        UIMaster.Instance.StartScreen("Screen 2", DisplayOptions.Build());
        // Use custome
        UIMaster.Instance.StartScreen("Screen 2", DisplayOptions.Build().SetScreenFade(false));
        UIMaster.Instance.StartScreen("Screen 2", DisplayOptions.Build().SetUpon(false));
于 2017-07-06T07:07:09.503 回答
-1

这应该工作

public struct MyStruct 
{
    private string myName;
    private int? myNumber;
    private bool? myBoolean;
    private MyRefType myType;

    public string MyName
    {
        get { return myName ?? "Default name"; }
        set { myName= value; }
    }
    public int MyNumber
    {
        get { return myNumber ?? 42; }
        set { myNumber = value; }
    }
    public bool MyBoolean
    {
        get { return myBoolean ?? true; }
        set { myBoolean = value; }
    }
    public MyRefType MyType 
    {
        get { return myType ?? new MyRefType(); }
        set { myType = value; }
    }

    //optional
    public MyStruct(string myName = "Default name", int myNumber = 42, bool myBoolean = true)
    {
        this.myType = new MyRefType();
        this.myName = myName;
        this.myNumber = myNumber;
        this.myBoolean = myBoolean;
    }
}

[TestClass]
public class MyStructTest
{
    [TestMethod]
    public void TestMyStruct()
    {
        var myStruct = default(MyStruct);
        Assert.AreEqual("Default name", myStruct.MyName);
        Assert.AreEqual(42, myStruct.MyNumber);
        Assert.AreEqual(true, myStruct.MyBoolean);
        Assert.IsNotNull(myStruct.MyType);
    }
}
于 2014-05-02T20:30:20.443 回答
-1

这可能有效...

    public struct MyStruct
    {
        private bool _name;
        public string myName
        {
            get { return (_name ? myName : "Default name"); }
            set { _name = true; myName = value; }
        }
        private bool _num;
        public int myNumber 
        {
            get { return (_num ? myNumber : 42); }
            set { _num = true; myNumber = value; }
        }
        private bool _bool;
        public bool myBoolean
        {
            get { return (_bool ? myBoolean : true); }
            set { _bool = true; myBoolean = value; }
        }
        private bool _type;
        public MyRefType myType
        {
            get { return _type ? myType : new MyRefType(); }
            set { _type = true; myType = value; }
        }
    }

没关系 StackOverflowException

于 2014-10-28T19:36:52.240 回答
-3

有一个解决方法

public struct MyStruct
{
    public MyStruct(int h = 1, int l = 1)
    {
        high = h;
        low = l;
    }
    public int high;
    public int low;
}
于 2013-05-23T19:37:57.257 回答