Переопределение значений по умолчанию в структуре (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);
12 ответов
конструкторы Struct аналогичны конструкторы классов, за исключением следующие отличия:
структуры не могут содержать явные конструкторы без параметров. Структура члены автоматически инициализируются к их значениям по умолчанию. Структура не может иметь инициализатор в форма: база (аргумент-список).
http://msdn.microsoft.com/en-us/library/aa288208 (v=против 71).aspx
Итак, короткий ответ, Нет вы невозможно переопределить конструктор по умолчанию (каждая структура имеет конструктор без параметров, и его нельзя скрыть или переопределить)...
ты не можешь. Структуры всегда имеют конструктор по умолчанию, который устанавливает для каждого элемента значение по умолчанию (null
для ссылочных типов, 0
для числовых типов, false
для bools, etc.) Это поведение нельзя изменить.
вы не можете переопределить конструктор по умолчанию (без параметров) для структуры. Можно добавлять только новые конструкторы, которые принимают параметры.
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;
}
существует обходной путь, чтобы это произошло с помощью пользовательских геттеров свойств. Заметьте:
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 }; }
}
}
мое решение. Это тоже работает.
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; }
}
}
Nevermind StackOverflowException
существует решение
public struct MyStruct
{
public MyStruct(int h = 1, int l = 1)
{
high = h;
low = l;
}
public int high;
public int low;
}