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

发布于 2024-10-08 08:24:26 字数 383 浏览 7 评论 0原文

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

作为示例,我有一个

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

Is it possible to set or override the default state for a structure?

As an example I have an

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

and a structure that links 2 values for that enum

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

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

But can I specify that the default state is

SomethingData(something.c,0,1);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

挽梦忆笙歌 2024-10-15 08:24:26

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

结构体不能包含显式的
无参数构造函数。结构体
成员自动初始化
为其默认值。一个结构体
中不能有初始化程序
形式:基础(参数列表)。

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

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

Struct constructors are similar to
class constructors, except for the
following differences:

Structs cannot contain explicit
parameterless constructors. Struct
members are automatically initialized
to their default values. A struct
cannot have an initializer in the
form: base (argument-list).

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

So, short answer, no you can't override the default constructor (every struct has a parameterless constructor and you can't hide it or override it)...

却一份温柔 2024-10-15 08:24:26

你不能。结构体始终有一个默认构造函数,用于将每个成员设置为其默认值(引用类型为 null,数字类型为 0,布尔值为 false,等)此行为无法更改。

You can't. Structs always have a default constructor that sets every member to its default value (null for reference types, 0 for numeric types, false for bools, etc.) This behavior cannot be changed.

对你而言 2024-10-15 08:24:26

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

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

You can't override the default (parameterless) constructor for a struct. You can only add new constructors, which take parameters.

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

会发光的星星闪亮亮i 2024-10-15 08:24:26

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

当类类型存储位置出现时,它最初将保存一个空引用。当结构类型存储位置存在时,其所有字段(以及其中结构的任何字段)将同时存在。与只能通过使用构造函数来存在的类对象实例不同,结构类型存储位置的存在无需使用任何结构自身的代码。因此,结构的定义不会决定当“实例”[即结构类型存储位置]出现时会发生什么。

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

Creating a class object will cause all of the instance fields to come into existence before anything--even the class constructor--can access it, and allocating an array will cause all of its elements to exist before anything can access the array. Both of these actions will cause all of the memory allocated to those fields or elements to be zeroed out without regard for the data types to be stored therein.

When a class-type storage location comes into existence, it will initially hold a null reference. When a structure-type storage location comes into existence, all of its fields (and any fields of structures within it) will do so simultaneously. Unlike class object instances which can only come into existence by using a constructor, structure-type storage locations are brought into existence without using any of the structure's own code. Consequently, the structure's definition will have no say in what should happen when "instances" [i.e. struct-type storage locations] come into existence.

A struct is, fundamentally, a collection of fields bound together with duct tape. If a struct is supposed to behave like something else, it should typically make its fields private and pretend to be immutable [even though struct assignment actually mutates the destination struct by overwriting all its fields with the corresponding values from the source, and the struct definition gets no say in the matter]. If, however, a struct is supposed to encapsulate a fixed set of related but independent values (e.g. the coordinates of a point), which may independently accommodate any combination of values which are legal for their respective types, a struct should simply expose its fields publicly. Some people may whine about "mutable structs are evil", but the evils only apply when invoking self-mutating methods on a struct. Structs which expose their state as fields behave like collections of variables stuck together with duct tape. If what one needs is a collection of variables stuck together with duct tape, trying to make a struct pretend to be immutable will simply make it harder to program with.

智商已欠费 2024-10-15 08:24:26

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

这仅适用于值类型(可以用 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 }; }
    }
}

There is a workaround to make this happen by using custom Property getters. Observe:

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

This will only work for value types (which can be wrapped with nullable) but you could potentially do something similar for reference types by wrapping them in a generic class like below:

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 }; }
    }
}
━╋う一瞬間旳綻放 2024-10-15 08:24:26

有些相关:我经常想将新的对象初始值设定项语法与不可变值类型一起使用。但是,考虑到典型的不可变值类型实现的性质,无法利用该语法,因为属性是只读的。

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

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

Somewhat related: I've often wanted to use the new object initializer syntax with an immutable value type. However, given the nature of a typical immutable value type implementation, there is no way to utilize that syntax, since the properties are read-only.

I've come up with this approach; In my opinion this still satisfies the immutability of the value type, but allows the code that is responsible for instantiating the value type greater control over the initialization of the internal data.

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);
    }
}
傾城如夢未必闌珊 2024-10-15 08:24:26

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

        ...
    }
}

Each time you get/set property you need to set default value call InitDefaultValues() method

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, ".");

        ...
    }
}
她说她爱他 2024-10-15 08:24:26

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

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

My solution. It works as well.

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 value

        // 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));
不及他 2024-10-15 08:24:26

这应该有效

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

this should work

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);
    }
}
浅忆 2024-10-15 08:24:26

有点愚蠢,但有效

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

Kinda dumb, but works

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;
}
独行侠 2024-10-15 08:24:26

这可能有效...

    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

This may work...

    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

我很OK 2024-10-15 08:24:26

有一个解决方法

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

There is a workaround

public struct MyStruct
{
    public MyStruct(int h = 1, int l = 1)
    {
        high = h;
        low = l;
    }
    public int high;
    public int low;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文