Переопределение значений по умолчанию в структуре (С#)

Можно ли установить или переопределить состояние по умолчанию для структуры?

В качестве примера у меня есть

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 и т.д.). Это поведение не может быть изменено.

Ответ 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;
}