覆盖结构中的默认值(c#)

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

作为一个例子,我有一个

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); 

结构构造函数类似于类构造函数,但以下差异除外:

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

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

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

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

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

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

创建一个类对象将导致所有实例字段在任何事物之前出现 – 甚至类构造函数 – 都可以访问它,并且分配数组将导致所有元素在任何可以访问数组之前存在。 这两个动作都将导致分配给那些字段或元素的所有存储器被清零, 而不考虑要存储在其中的数据类型

当类类型存储位置出现时,它最初将保持空引用。 当结构类型存储位置出现时,其所有字段(以及其中的任何结构字段)将同时这样做。 与只能通过使用构造函数生成的类对象实例不同,结构类型存储位置在不使用任何结构自身代码的情况下生成。 因此,当“实例”[即结构类型存储位置]存在时,结构的定义将无法说明应该发生什么。

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

有些相关:我经常想要使用具有不可变值类型的新对象初始化器语法。 但是,鉴于典型的不可变值类型实现的性质,没有办法利用该语法,因为属性是只读的。

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

 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); } } 

每次获取/设置属性时,都需要设置默认值调用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, "."); ... } } 

有点愚蠢,但有效

 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; } 

有一种解决方法可以通过使用自定义属性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包装),但是你可以通过将它们包装在如下所示的generics类中来为引用类型执行类似的操作:

 public class Wrapper { public TValue Value { get; set; } } public struct Foostruct { private Wrapper _tick; public Tick Tick { get { return _tick == null ? new Tick(20) : _tick.Value; } set { _tick = new Wrapper { Value = value }; } } } 

我的解决方案 它也有效。

 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)); 

这应该工作

 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); } } 

这可能有用……

  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

有一个解决方法

 public struct MyStruct { public MyStruct(int h = 1, int l = 1) { high = h; low = l; } public int high; public int low; }