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

时间:2010-12-21 17:15:19

标签: c# struct defaults

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

作为一个例子,我有一个

enum something{a,b,c,d,e};

和一个链接该枚举的两个值的结构

struct SomethingData
{
    something type;
    int Value;
    double Multipler;

    SomethingData(something enumVal, int intVal, double DblVal) {...}
}

但是我可以指定默认状态是

SomethingData(something.c,0,1);

12 个答案:

答案 0 :(得分:11)

  

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

     

结构不能包含显式   无参数构造函数。结构   成员会自动初始化   到他们的默认值。结构   不能有一个初始化器   form:base(argument-list)。

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

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

答案 1 :(得分:6)

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

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

        ...
    }
}

答案 6 :(得分:0)

有点傻,但有效

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

答案 7 :(得分:0)

有一种解决方法可以通过使用自定义属性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; }
    }
}

这只适用于值类型(可以用可空包装),但你可以通过将它们包装在如下所示的泛型类中来为引用类型执行类似的操作:

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

答案 8 :(得分:0)

我的解决方案。它也有效。

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

答案 9 :(得分:-1)

这应该有效

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

答案 10 :(得分:-1)

这可能有用......

    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

答案 11 :(得分:-3)

有一种解决方法

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