Laden...

Nullable für Referenztypen

Erstellt von Uwe81 vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.589 Views
U
Uwe81 Themenstarter:in
282 Beiträge seit 2008
vor 13 Jahren
Nullable für Referenztypen

Hallo!

Die Frage klingt blöd, aber ist ernst gemeint: Warum gibt es kein Nullable für Referenztypen. Man kann es recht leicht nachprogrammieren, aber warum wurde die Beschränkung auf Value-Typen .NET explizit gefordert?

Hintergrund: Ich habe eine Generische Klasse MyFoo<T>. Diese hat nun eine Membervariable vom Typ T, die entweder einen Wert haben kann oder auch nicht.

Ist T nun Reference-Type, kann ich es - wenn kein Wert vorhanden - auf null setzen.
Ist T nun Value-Type, kann ich ein Nullable<T> speichern und es - wenn kein Wert vorhanden - auf null setzen.

Kann T beides sein geht aber weder das eine noch das andere. Default(T) geht nicht, da zwar null für Referenztypen ein sinnvolles "hat keinen Wert" ist, 0 für Integer aber sehr wohl auch einen sinnvollen Wert darstellen kann.

Viele Grüße,
Uwe

B
387 Beiträge seit 2005
vor 13 Jahren

An deiner Stelle würde ich an die Klasse MyFoo<T> einfach eine Bedingung anfügen, dass nur Referenztypen erlaubt sind.

Also so:


public class MyFoo<T>
    where T : class

Ein Nullable für einen Referenztyp macht keinen Sinn, da ja ein Referenztyp im Prinzip schon Nullable (= erlaubt Null-Wert) ist.

Gruß

Gelöschter Account
vor 13 Jahren

referenztypen kannst du auf null setzen. daher ist das nullable<t> absolut sinnfrei.

für deinen fall könntest du boxing einsetzen und die membervariable als object speichern.

alternativ kannst du auch eine boolsche variable halten, die angibt, ob der wert eigendlich null ist oder nciht... kommt aber darauf an inwieweit der valuetype nach ausen hin sichtbar sein soll.

F
60 Beiträge seit 2010
vor 13 Jahren

Referenztypen sind nullable. Versuch mal folgendes:
Nullable type as a generic parameter possible?

U
Uwe81 Themenstarter:in
282 Beiträge seit 2008
vor 13 Jahren

alternativ kannst du auch eine boolsche variable halten, die angibt, ob der wert eigendlich null ist oder nciht

Eigentlich suchte ich genau sowas, aber eben an den Wert gebunden.

Hab nun mal einen "UndefinableValue"-Wrapper geschrieben:


    public struct UndefinableValue<T> {
        T value;
        bool hasValue;

        /// <summary>
        /// Gets the value, if the <see cref="HasValue"/> property is true. 
        /// An exception is thrown if the <see cref="HasValue"/> property is false.
        /// </summary>
        /// <exception cref="System.InvalidOperationException">If the <see cref="HasValue"/> property is false.</exception>
        public T Value {
            get {
                if (!hasValue) {
                    throw new InvalidOperationException("Value is not defined;");
                }
                return value;
            }
        }

        /// <summary>
        /// If the <see cref="HasValue"/> property is true, the value is returned.
        /// If the <see cref="HasValue"/> property is false, the default value of the type is returned.
        /// </summary>
        /// <returns>Value of this instance or the default value.</returns>
        public T GetValueOrDefault() {
            return GetValueOrDefault(default(T));
        }

        /// <summary>
        /// If the <see cref="HasValue"/> property is true, the value is returned.
        /// If the <see cref="HasValue"/> property is false, the specified default value is returned.
        /// </summary>
        /// <returns>Value of this instance or the default value.</returns>
        public T GetValueOrDefault(T defaultValue) {
            return hasValue ? Value : default(T);
        }

        /// <summary>
        /// Gets a value indicating whether the current object has a value.
        /// </summary>
        public bool HasValue { get { return hasValue; } }

        /// <summary>
        /// Initializes a new instance of the <see cref="UndefinableValue&lt;T&gt;"/> struct with value.
        /// The <see cref="HasValue"/> Property will be true.
        /// </summary>
        /// <param name="value">The value.</param>
        public UndefinableValue(T value) {
            this.value = value;
            this.hasValue = true;
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="T"/> to <see cref="Itwm.Opt.Controls.MultiCriteria.PresenterComponents.UndefinableValue&lt;T&gt;"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator UndefinableValue<T>(T value) {
            return new UndefinableValue<T>(value);
        }

        /// <summary>
        /// Immutable representation of an undefined value.
        /// </summary>
        public static readonly UndefinableValue<T> Undefined = new UndefinableValue<T>();
    }

Dabei ist mir auch ein Grund aufgefallen, warum Nullable evtl. nur für Structs definiert ist. So ist es für Referenztypen möglich, ein neues UndefinableValue-Objekt zu erstellen, für das "HasValue" true ist, aber der Value "null". Das mag zwar manchmal sinnvoll sein, fühlt sich aber komisch an.

J
1.114 Beiträge seit 2007
vor 13 Jahren

Einen Value-Type kann man auch null setzen:

Int32? i = null;
Gelöschter Account
vor 13 Jahren

@Jelly:
du verwendest in deinem beispiel einen "nullable" type.... hier hat der syntaxzucker dein verständniss getrübt 😉

3.971 Beiträge seit 2006
vor 13 Jahren

Man könnte zusätzlich noch einen Zuweisungoperator und einen Vergleichsoperator hinzufügen, beide vom Typ Object. Wird etwas anderes als null übergeben, sollte hingegen eine Exception geworfen werden.

man muss dann nur aupfassen, dass man nicht sowas bastelt:


UndefinableValue<Foo> foo = ...;
bool bar = false;

if (foo == bar) {
}

Der Fehler würde erst zur Laufzeit auftreten und nicht schon zur Compilezeit.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...