Переопределение значений по умолчанию в структуре (С#)
Можно ли установить или переопределить состояние по умолчанию для структуры?
В качестве примера у меня есть
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);
Ответы
Ответ 1
Конструкторы Struct аналогичны класса, за исключением следующие отличия:
Структуры не могут содержать явные безразмерные конструкторы. Struct члены автоматически инициализируются к их значениям по умолчанию. Структура не может иметь инициализатор в form: base (список аргументов).
http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx
Итак, короткий ответ, вы не можете переопределить конструктор по умолчанию (каждая структура имеет конструктор без параметров и вы не можете скрыть его или переопределить)...
Ответ 2
Вы не можете. Структуры всегда имеют конструктор по умолчанию, который устанавливает для каждого члена значение по умолчанию (null
для ссылочных типов, 0
для числовых типов, false
для bools и т.д.). Это поведение не может быть изменено.
Ответ 3
Вы не можете переопределить конструктор по умолчанию (без параметров) для структуры. Вы можете добавлять только новые конструкторы, которые принимают параметры.
http://csharp.2000things.com/2010/10/03/108-defining-a-constructor-for-a-struct/
Ответ 4
Создание объекта класса приведет к тому, что все поля экземпляра появятся перед чем-либо - даже конструктор класса - смогут получить к нему доступ, а выделение массива приведет к тому, что все его элементы будут существовать, прежде чем что-либо сможет получить доступ к массиву, Оба этих действия приведут к обнулению всей памяти, выделенной этим полям или элементам, без учета типов данных, которые будут храниться в них.
Когда создается место хранения типа класса, вначале оно будет содержать нулевую ссылку. Когда создается хранилище структурного типа, все его поля (и любые поля структур внутри него) будут делать это одновременно. В отличие от экземпляров объектов класса, которые могут возникнуть только при использовании конструктора, хранилища структурного типа создаются без использования какого-либо собственного кода структуры. Следовательно, определение структуры не будет говорить о том, что должно произойти, когда "экземпляры" [т. структурных хранилищ].
Структура, по сути, представляет собой совокупность полей, связанных вместе с клейкой лентой. Если структура должна вести себя как что-то еще, она обычно должна делать свои поля частными и претендовать на неизменность [хотя назначение структуры фактически мутирует целевую структуру, перезаписывая все ее поля соответствующими значениями из источника, а определение структуры не имеет права говорить в этом вопросе]. Если, однако, предполагается, что структура должна инкапсулировать фиксированный набор связанных, но независимых значений (например, координат точки), , который может независимо принимать любую комбинацию значений, которые являются законными для их соответствующих типов, структура должна просто публиковать свои поля. Некоторые люди могут скулить о том, что "изменчивые структуры являются злыми", но зло применяется только при вызове методов самонастраивания в структуре. Структуры, которые выставляют свое состояние как поля, ведут себя подобно совокупности переменных, склеенных вместе с клейкой лентой. Если вам нужно, это набор переменных, склеенных вместе с клейкой лентой, пытаясь заставить конструкцию притворяться неизменной, просто будет сложнее программировать.
Ответ 5
В некоторой степени связаны: я часто хотел использовать синтаксис инициализатора нового объекта с неизменяемым типом значений. Однако, учитывая характер типичной реализации типа неизменяемого значения, нет способа использовать этот синтаксис, поскольку свойства доступны только для чтения.
Я придумал такой подход; По-моему, это все еще удовлетворяет неизменности типа значения, но позволяет коду, ответственному за создание экземпляра типа значения, большего контроля над инициализацией внутренних данных.
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);
}
}
Ответ 6
Каждый раз, когда вы получаете/устанавливаете свойство, вам нужно установить значение по умолчанию для вызова метода 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, ".");
...
}
}
Ответ 7
Скрытность, но работает
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;
}
Ответ 8
Существует обходное решение, чтобы это произошло, используя пользовательские свойства getters. Обратите внимание:
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; }
}
}
Это будет работать только для типов значений (которые могут быть обернуты с помощью NULL), но вы могли бы сделать что-то подобное для ссылочных типов, обернув их в общий класс, как показано ниже:
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 }; }
}
}
Ответ 9
Мое решение. Он также работает.
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));
Ответ 10
это должно работать
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);
}
}
Ответ 11
Это может сработать...
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; }
}
}
Nevermind StackOverflowException
Ответ 12
Существует обходное решение
public struct MyStruct
{
public MyStruct(int h = 1, int l = 1)
{
high = h;
low = l;
}
public int high;
public int low;
}