Sovrascrivere le impostazioni Predefinite in una struttura (c#)

È possibile impostare o modificare l’impostazione predefinita di stato per una struttura?

Come esempio ho un

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

e una struttura che collega 2 valori enum

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

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

Ma posso specificare che lo stato di default è

SomethingData(something.c,0,1);
  • Si potrebbe impostare a -2 (così, c=0). O forse anche di creare un Predefinito costante (o meglio, di sola lettura statica).
InformationsquelleAutor | 2010-12-21



12 Replies
  1. 13

    Struct costruttori sono simili a
    il costruttore della classe, fatta eccezione per il
    seguenti differenze:

    Le strutture non possono contenere esplicito
    costruttori senza parametri. Struct
    i membri sono inizializzate automaticamente
    ai loro valori di default. Una struct
    non può avere un inizializzatore in
    forma: base (argomento-lista).

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

    Così, a risposta breve, no, non puoi ignorare il costruttore di default (ogni struttura ha un costruttore senza parametri e non è possibile nascondere o sovrascrivere)…

    • che ne dite di un lavoro intorno che consente di specificare quali i valori di default sono? il meglio che posso venire con è la creazione di una costante istanza della struttura, nella struttura e quindi impostare il valore a questo invece di chiamare il costruttore di default
    • Si potrebbe fare che. Ma questo non può nascondere o eliminare il tipo di default del costruttore. (Si noti che è necessario utilizzare un static readonly campo per questo invece di un const, dal momento che i campi di una struct di tipo non può essere effettuata costante).
    • ringrazio il readonly è quello che avevo dimenticato
    • È un peccato, però, soprattutto quando si dichiara un array di alcuni struct, e voleva una particolare struttura membri di un particolare valore di default … hai per scorrere l’array e impostare. (Per esempio, ho portato un algoritmo da un C che ha dato un significato speciale per ‘-1’). Ma anche se è più di codice, forse non fa più lavoro che se ci è stato permesso di indicare valori di default?
    • Come circa la creazione di una proprietà statica Default che crea di default del tuo oggetto? Invece di chiamare new Foo(), si sarebbe chiamata Foo.Default. Questo contiene i valori di default in un posto centrale e fornisce la quantità minima di codice aggiuntivo.
  2. 8

    Non si può. Le strutture hanno sempre un costruttore di default che imposta ogni membro al suo valore di default (null per i tipi di riferimento, 0 per i tipi numerici, false per bools, etc.) Questo comportamento non può essere modificato.

    • Per quanto riguarda le Enumerazioni?
    • Edit, appena controllato. Le enumerazioni di default per il primo indice di enumerazione. Questo è in realtà estremamente potente, soprattutto se il primo indice è dichiarato “Nessuno”.
    • Essi in realtà di default per qualunque enumerazione membro ha il valore 0, che sarà di fatto il primo, se non esplicitamente assegnare valori. Ma se fai una cosa del genere enum Foo { A = 1, B = 0 } allora vi accorgerete che default(Foo) == Foo.B invece. Se l’enumerazione non hanno membri con il valore 0, allora il valore di default non sarà uno dei tuoi enum opzioni a tutti.
  3. 1

    Creazione di un oggetto di classe farà sì che tutti i campi dell’istanza di venire in esistenza prima di tutto, anche il costruttore della classe–di accesso, e l’allocazione di un array causa di tutti i suoi elementi di esistere prima di tutto può accedere alla matrice. Entrambe queste azioni causano tutta la memoria allocata per i campi o elementi per essere azzerata , senza riguardo per i tipi di dati da esso memorizzati.

    Quando una classe-tipo di percorso di archiviazione viene in esistenza, inizialmente a tenere un riferimento null. Quando una struttura-tipo di posizione di memorizzazione, viene in essere, tutti i suoi campi e i campi di strutture all’interno di essa) di farlo contemporaneamente. A differenza di classe istanze di un oggetto che non può venire in esistenza utilizzando un costruttore, la struttura-tipo di posizioni di archiviazione sono portati in esistenza senza l’utilizzo di qualsiasi struttura del proprio codice. Di conseguenza, la struttura della definizione dovrà dire di no a ciò che dovrebbe accadere quando le “istanze” [cioè di una struttura-tipo di posizioni di archiviazione] venire in esistenza.

    Una struct è, fondamentalmente, un insieme di campi tenuti insieme con nastro adesivo. Se una struct dovrebbe comportarsi come un altro, in genere deve fare i suoi campi privati e far finta di essere immutabile [anche se la struttura di assegnazione, in realtà, muta la destinazione struct sovrascrivendo tutti i suoi campi con i valori corrispondenti della sorgente, e la definizione della struttura non ottiene alcuna voce in capitolo in questione]. Se, tuttavia, una struttura che dovrebbe racchiudere un insieme fisso di collegate ma indipendenti valori (ad esempio le coordinate di un punto), che possono autonomamente di adattarsi a qualsiasi combinazione di valori che sono legali per i rispettivi tipi, una struttura che dovrebbe semplicemente esporre i suoi campi pubblicamente. Alcune persone possono lamentarsi di “mutevole strutture sono il male”, ma il mali si applicano solo in caso di richiamo di auto-modificarsi metodi di una struct. Le strutture che espongono il loro stato come campi si comportano come le collezioni di variabili incollati con nastro adesivo. Se ciò che uno ha bisogno è una collezione di variabili incollati con nastro adesivo, cercando di fare una struct finta di essere immutabile semplicemente rendere più difficile la programmazione.

  4. 0

    In qualche modo collegate: ho spesso voluto utilizzare il nuovo inizializzatore di oggetto sintassi con un immutabile tipo di valore. Tuttavia, data la natura di una tipica immutabile valore tipo di implementazione, non c’è modo di utilizzare la sintassi, visto che le proprietà sono di sola lettura.

    Ho venire con questo approccio, A mio parere, questo soddisfa l’immutabilità del tipo di valore, ma consente il codice che è responsabile della creazione di un’istanza del tipo di valore maggiore controllo sull’inizializzazione dei dati interni.

    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);
        }
    }
    • Non è questo il ImmutableValueType un mutevole tipo? (dal momento che può essere modificato tramite l’Infusore tipo) penso che questo è ciò che i costruttori sono per
    • Può essere disordinato/noioso scrivere diversi costruttore sovraccarichi, per soddisfare ogni possibile modo per inizializzare un oggetto. Per quanto riguarda l’immutabilità: come ho già detto, a mio parere, l’immutabilità è mantenuto. Non è possibile ottenere un riferimento al “immutabile” oggetto senza chiamare infusore di prodotti metodo (ok, ho fatto aggiungere una conversione implicita operatore, quindi, è la vostra chiamata se si desidera rimuovere). Una volta che il valore è stato restituito da infusore di un prodotto metodo, infusore non è più possibile modificare tale valore, poiché in questo caso si tratta di un tipo di valore.
  5. 0

    Ogni volta che si ottenere/impostare la proprietà è necessario impostare il valore predefinito di chiamata InitDefaultValues() metodo

    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, ".");
    
            ...
        }
    }
    • Le strutture non devono mutare se stessi in proprietà getter. Se MyObject.Foo è un campo il cui sottostante tipo è il tipo di struttura, quindi la lettura MyObject.Foo.NumberDecimalSeparator di catturare la cultura corrente; se si tratta di una struttura di quel tipo, quindi la lettura MyObject.Foo.NumberDecimalSeparator crea una copia temporanea della struttura sottostante, cattura la cultura corrente, in copia, calcolare il valore di ritorno di NumberDecimalSeparator, e abbandonare la struttura temporanea.
  6. 0

    Un po ‘ stupido, ma funziona

    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

    C’è una soluzione per rendere questo accada personalizzati utilizzando Proprietà getter. Osservare:

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

    Questo funziona solo per i tipi di valore (che può essere avvolto con nullable), ma si potrebbe fare qualcosa di simile per i tipi di riferimento avvolgendo in una classe generica, come di seguito:

    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

    La mia soluzione. Funziona anche.

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

    Usare il valore predefinito

            //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

    questo dovrebbe funzionare

    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);
        }
    }
    • Se voi passare in modo esplicito null per myName si finisce con il valore di default, che non dovrebbe accadere. Se si assegna null per MyType, stesso problema. Anche voi non dovrebbe avere un mutevole tipo di riferimento. Stanno male. Infine, avendo proprietà è in realtà un importante semantica differenza dalla presenza di campi, come in OP, in particolare quando si tratta di affrontare il mutevole tipi di riferimento (che è una ragione perché sono così male).
    • che cosa succede se io rimuovere MyType e MyName e utilizzare solo i tipi di valore all’interno della struttura? è che ancora non corretto? Il mio obiettivo è quello di avere una struttura MyConfig che contiene un paio di bool che per impostazione predefinita è true in modo che io possa usare come predefinito param così: public void MyMethod(MyConfig config = default(MyConfig)) { //... } Grazie.
    • È ancora cambiare la semantica della struttura, modificando i campi di proprietà, sì. Se fosse immutabile, che probabilmente non sarebbe un problema.
  10. -1

    Questo può funzionare…

        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

    • spiegare di più…
    • Ho pensato che il bool associati a ciascuna variabile di inizializzazione per falso poi cambiare a true se il valore è stato modificato al di fuori del costruttore.
  11. -3

    C’è una soluzione

    public struct MyStruct
    {
        public MyStruct(int h = 1, int l = 1)
        {
            high = h;
            low = l;
        }
        public int high;
        public int low;
    }
    • Idea intelligente, ma non funziona … l’avete provate? Chiamata new MyStruct() ancora produce un oggetto con high e low set a 0.
    • Hai ragione @cdhowie, ho appena provato la compilazione. Almeno si afferma che non funziona così e nessuno potrà provare hahaha.

Lascia un commento