Переопределение значений по умолчанию в структуре (c #) - PullRequest
15 голосов
/ 21 декабря 2010

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

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

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 ]

11 голосов
/ 21 декабря 2010

Конструкторы структур похожи на конструкторы классов, за исключением следующих отличий:

Структуры не могут содержать явных конструкторов без параметров.Члены структуры автоматически инициализируются к их значениям по умолчанию.Структура не может иметь инициализатор в форме: base (аргумент-список).

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

Итак, короткий ответ, нет, вы не можете переопределить конструктор по умолчанию (каждая структура имеет конструктор без параметров, и вы не можете его скрыть или переопределить) ...

6 голосов
/ 21 декабря 2010

Вы не можете. Структуры всегда имеют конструктор по умолчанию, который устанавливает для каждого члена значение по умолчанию (null для ссылочных типов, 0 для числовых типов, false для bools и т. Д.) Это поведение нельзя изменить.

1 голос
/ 24 мая 2013

Создание объекта класса приведет к тому, что все поля экземпляра появятся прежде, чем что-либо - даже конструктор класса - сможет получить к нему доступ, а выделение массива приведет к существованию всех его элементов, прежде чем что-либо сможет получить доступ к массиву , Оба этих действия приведут к обнулению всей памяти, выделенной этим полям или элементам , без учета типов данных, которые будут храниться в них .

Когда место хранения типа класса появляется, оно первоначально будет содержать нулевую ссылку. Когда место хранения структурного типа появляется, все его поля (и любые поля структур внутри него) делают это одновременно. В отличие от экземпляров объектов класса, которые могут появиться только при использовании конструктора, места хранения структурного типа создаются без использования какого-либо собственного кода структуры. Следовательно, определение структуры не будет иметь права голоса в отношении того, что должно произойти, когда «экземпляры» [т.е. складские помещения типа структуры].

Структура, по сути, представляет собой набор полей, связанных вместе клейкой лентой. Если структура должна вести себя как-то иначе, она обычно должна делать свои поля приватными и притворяться неизменными [даже если присваивание структуры на самом деле изменяет структуру назначения, перезаписывая все ее поля соответствующими значениями из источника, и определение структуры не имеет права голоса в этом вопросе. Однако если предполагается, что структура инкапсулирует фиксированный набор связанных, но независимых значений (например, координат точки), , которые могут независимо вместить любую комбинацию значений, которые допустимы для их соответствующих типов , a Структура должна просто обнародовать свои поля. Некоторые люди могут скулить о том, что «изменчивые структуры - это зло», но зло применимо только при вызове методов самопутывания в структуре. Структуры, которые выставляют свое состояние как поля, ведут себя как наборы переменных, склеенных клейкой лентой. Если вам нужен набор переменных, склеенных клейкой лентой, попытка сделать структуру, притворяющейся неизменной, просто усложнит программирование.

1 голос
/ 21 декабря 2010

Вы не можете переопределить конструктор по умолчанию (без параметров) для структуры. Вы можете добавлять только новые конструкторы, которые принимают параметры.

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

0 голосов
/ 06 июля 2017

Мое решение. Это работает также.

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));
0 голосов
/ 21 ноября 2016

Существует способ обойти это, используя пользовательские методы получения свойств. Обратите внимание:

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 }; }
    }
}
0 голосов
/ 13 января 2016

Вроде тупой, но работает

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;
}
0 голосов
/ 28 октября 2014

Это может сработать ...

    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

0 голосов
/ 03 мая 2014

это должно работать

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);
    }
}
0 голосов
/ 09 июня 2013

Каждый раз, когда вы получаете / устанавливаете свойство, вам нужно установить значение по умолчанию, вызывая метод 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, ".");

        ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...