Windows Azure Cloud Storage ermöglicht es Ihnen bereits ab 0,10€ pro GB/Monat die Vorteile der Cloud zu nutzen.
Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Advanced Developers Conference     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: C# und .NET ::  Properties vor null Zuweisung schützen     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
Dravere
Moderator

Benutzerprofil
Anmeldungsdatum: 13.06.2005
Beiträge: 7252
Beitrag Dravere Moderator 11:15:04 31.08.2010   Titel:   Properties vor null Zuweisung schützen            Zitieren

Hallo zusammen,

Kurzes Code-Beispiel:
C# Code:
public class MyClass
{
  public string Name { get; set; }
}
C# Code:
public class MyClass
{
public string Name { get; set; }
}
C# Code:
public class MyClass
{
  public string Name { get; set; }
}

Wie kann ich am einfachsten Name davor schützen, dass jemand null zuweisst. Das einzige was ich kenne ist:
C# Code:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
  private string m_name;

  public string Name
  {
    get { return m_name; }
    set { m_name = (value != null ? value : "" /* oder throw oder was auch immer */); }
  }
}
C# Code:
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
private string m_name;

public string Name
{
get { return m_name; }
set { m_name = (value != null ? value : "" /* oder throw oder was auch immer */); }
}
}
C# Code:
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
  private string m_name;

  public string Name
  {
    get { return m_name; }
    set { m_name = (value != null ? value : "" /* oder throw oder was auch immer */); }
  }
}

Gibt es da keine einfachere Lösung? Mir geht es langsam auf den Nerv, dass ich nur wegen null immer wieder diesen Code schreiben muss. Inzwischen ist er sogar schon als Snippet vorhanden. Die ganze Zeit muss man auf null prüfen ...

Grüssli

_________________
Danke für die Hilfe, Antwort oder Meinung!
C++: Std-Lib Referenz
C# .Net: MSDN kennt die Antwort
Firefighter
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.03.2007
Beiträge: 2726
Beitrag Firefighter Mitglied 11:17:17 31.08.2010   Titel:              Zitieren

Mach den Setter doch einfach private und erlaube nur eine einmale zuweisung über den ctor und dort prüfst du auf null und fertig.

_________________
Mein Blog
Clean-Code-Developer
Wie man richtig Fragen stellt
Firefighter
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.03.2007
Beiträge: 2726
Beitrag Firefighter Mitglied 11:19:20 31.08.2010   Titel:              Zitieren

Du kannst auch den geheimoperator nutzen :P
C# Code:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
  private string m_name;

  public string Name
  {
    get { return m_name; }
    set { m_name = value ?? string.Empty; }
  }
}
C# Code:
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
private string m_name;

public string Name
{
get { return m_name; }
set { m_name = value ?? string.Empty; }
}
}
C# Code:
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
  private string m_name;

  public string Name
  {
    get { return m_name; }
    set { m_name = value ?? string.Empty; }
  }
}

wäre das einfachste was mir grad einfällt wenn der setter unbedingt public sein muss.sorry für den doppelpost

_________________
Mein Blog
Clean-Code-Developer
Wie man richtig Fragen stellt
witte
Mitglied

Benutzerprofil
Anmeldungsdatum: 08.01.2008
Beiträge: 1295
Beitrag witte Mitglied 11:26:45 31.08.2010   Titel:              Zitieren

Hilft vllt ein null-Value_objekt? Dann entfällt zumindest die Prüfiung.
http://de.wikipedia.org/wiki/Nullobjekt_%28Entwurfsmuster%29
Firefighter
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.03.2007
Beiträge: 2726
Beitrag Firefighter Mitglied 11:31:23 31.08.2010   Titel:              Zitieren

Die Grundfrage die ich mir gestellt habe ist doch eher, warum du die Logik der Null-Prüfung unbedingt im Setter haben musst. Ich meine wenn jemand mit dem objekt arbeitet dann soll der sich gefälligst drum kümmern das da kein Null Zugewiesen wird, so ist es zumindest meine Erwartung.

_________________
Mein Blog
Clean-Code-Developer
Wie man richtig Fragen stellt
David W
Mitglied

Benutzerprofil
Anmeldungsdatum: 09.08.2005
Beiträge: 4588
Beitrag David W Mitglied 11:49:09 31.08.2010   Titel:              Zitieren

Wie wäre es mit dieser Idee?

C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
public static class PropertySetter
{
    public static string Set(string value)
    {
        if (value == null)
        {
            var propertyName = new StackFrame(1).GetMethod().Name;
            throw new ArgumentNullException(string.Format("The property {0} is empty", propertyName.Substring(4)));
        }
        return value;
    }
}
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
public static class PropertySetter
{
public static string Set(string value)
{
if (value == null)
{
var propertyName = new StackFrame(1).GetMethod().Name;
throw new ArgumentNullException(string.Format("The property {0} is empty", propertyName.Substring(4)));
}
return value;
}
}
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
public static class PropertySetter
{
    public static string Set(string value)
    {
        if (value == null)
        {
            var propertyName = new StackFrame(1).GetMethod().Name;
            throw new ArgumentNullException(string.Format("The property {0} is empty", propertyName.Substring(4)));
        }
        return value;
    }
}


C# Code:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
    private string m_name;

    public string Name
    {
        get { return m_name; }
        set { m_name = PropertySetter.Set(value); }
    }
}
C# Code:
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
private string m_name;

public string Name
{
get { return m_name; }
set { m_name = PropertySetter.Set(value); }
}
}
C# Code:
1
2
3
4
5
6
7
8
9
10
public class MyClass
{
    private string m_name;

    public string Name
    {
        get { return m_name; }
        set { m_name = PropertySetter.Set(value); }
    }
}

So sparst du dir Code Duplikation im sinne des DRY

_________________
My Libraries | aniwen
Dravere
Moderator

Benutzerprofil
Anmeldungsdatum: 13.06.2005
Beiträge: 7252
Beitrag Dravere Moderator 13:32:56 31.08.2010   Titel:              Zitieren

Firefighter schrieb:
Mach den Setter doch einfach private und erlaube nur eine einmale zuweisung über den ctor und dort prüfst du auf null und fertig.

Und was ist, wenn du den Namen des Objektes ändern möchtest? MyClass hat natürlich noch andere Eigenschaften, Methoden, usw. usf. Falls das nicht klar war :)

Firefighter schrieb:
Du kannst auch den geheimoperator nutzen :P

Den hatte ich tatsächlich ganz vergessen, danke für die Erinnerung. Er heisst übrigens nicht "Geheimoperator" sondern Null-coalescing Operator. Wobei ich allerdings zustimmen muss, dass Geheimoperator besser klingt und einfacher auszusprechen ist :D

Firefighter schrieb:
Die Grundfrage die ich mir gestellt habe ist doch eher, warum du die Logik der Null-Prüfung unbedingt im Setter haben musst. Ich meine wenn jemand mit dem objekt arbeitet dann soll der sich gefälligst drum kümmern das da kein Null Zugewiesen wird, so ist es zumindest meine Erwartung.

Jein. Es gibt auch das Problem, wenn das Objekt weiterverwendet wird. Dann muss man überall auch ausserhalb eine Prüfung auf null machen, obwohl null vielleicht einfach nur ein bescheuerter Wert ist. Man könnte natürlich dies alles in die Dokumentation schreiben und einfach auf eine NullReferenceException setzen. Und sagen: "Selber schuld, wenn du den Wert auf null setzt". Aber klingt für mich nicht nach einer guten Idee. Zudem tritt die NullReferenceException oder plötzliche ArgumentNullException bei der Übergabe an eine andere API, an einer völlig anderen Stelle auf, als dort wo der tatsächliche Fehler gemacht wurde.

witte schrieb:
Hilft vllt ein null-Value_objekt? Dann entfällt zumindest die Prüfiung.
http://de.wikipedia.org/wiki/Nullobjekt_%28Entwurfsmuster%29

Und wie soll man dies hier nun einsetzen? Ich möchte vielleicht hier nochmals darauf hinweisen, falls das wirklich nicht klar gewesen sein sollte:
MyClass hat natürlich noch andere Eigenschaften, Methoden, usw. usf. Ein Nullobjekt von MyClass und einem privaten Setter für Name geht nicht.

@CSL,
Ja, so verhindert man einen Teil der Codeduplizierung, daran habe ich auch schon gedacht. Extramember gibt es trotzdem noch und der Getter ist auch immer gleich. Man hat immer noch eine dämliche Dupplizierung :)
Zudem würde ich keine Reflections einsetzen, sondern der Methode Set einen zweiten Parameter übergeben.

Noch eine weitere ähnliche Möglichkeit wäre dies hier:
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public struct Property<ValueT>
  where ValueT : class
{
  private ValueT m_value;

  public Property(ValueT v)
  {
    m_value = v;
  }

  public static implicit operator ValueT(Property<ValueT> v)
  {
    return v.m_value;
  }

  public static implicit operator Property<ValueT>(ValueT v)
  {
    if(v == null)
    {
      throw new ArgumentNullException("value");
    }

    return new Property<ValueT>(v);
  }
}

public class MyClass
{
  public Property<string> Name { get; set; }
}
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public struct Property<ValueT>
where ValueT : class
{
private ValueT m_value;

public Property(ValueT v)
{
m_value = v;
}

public static implicit operator ValueT(Property<ValueT> v)
{
return v.m_value;
}

public static implicit operator Property<ValueT>(ValueT v)
{
if(v == null)
{
throw new ArgumentNullException("value");
}

return new Property<ValueT>(v);
}
}

public class MyClass
{
public Property<string> Name { get; set; }
}
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public struct Property<ValueT>
  where ValueT : class
{
  private ValueT m_value;

  public Property(ValueT v)
  {
    m_value = v;
  }

  public static implicit operator ValueT(Property<ValueT> v)
  {
    return v.m_value;
  }

  public static implicit operator Property<ValueT>(ValueT v)
  {
    if(v == null)
    {
      throw new ArgumentNullException("value");
    }

    return new Property<ValueT>(v);
  }
}

public class MyClass
{
  public Property<string> Name { get; set; }
}

Man könnte dann immer noch null zuweisen, indem man ein new Property<string>() zueweist, aber das würde dann schon fast mit böswilliger Absicht geschehen. Wirklich schön empfinde ich es aber auch nicht.

Grüssli

_________________
Danke für die Hilfe, Antwort oder Meinung!
C++: Std-Lib Referenz
C# .Net: MSDN kennt die Antwort
David W
Mitglied

Benutzerprofil
Anmeldungsdatum: 09.08.2005
Beiträge: 4588
Beitrag David W Mitglied 10:48:31 01.09.2010   Titel:              Zitieren

Also ich deine Lösung schick, was gefällt dir daran nicht?

Was die Duplikation an geht, das Problem hat man mit den "PropertyChanged" Strings für WPF auch.
http://www.mycsharp.de/wbb2/thread.php?threadid=80535
Mit Attribute ist da noch viel raus zu holen, aber trotzdem ist es dort leider unvermeidliche Duplikation. Man kann es maximal noch durch viel Overhead und Performance Einbußen schaffen => http://www.codeproject.com/KB/cs/NotifyingAttribute.aspx

_________________
My Libraries | aniwen
Dravere
Moderator

Benutzerprofil
Anmeldungsdatum: 13.06.2005
Beiträge: 7252
Beitrag Dravere Moderator 16:26:52 01.09.2010   Titel:              Zitieren

CSL schrieb:
Also ich deine Lösung schick, was gefällt dir daran nicht?

Es wirkt so gefrickelt, es riecht so nach Workaround. Ich weiss nicht. Wahrscheinlich würde ich mich erst mit einem nonnull Keyword der Sprache selbst zufrieden geben ...

Zudem habe ich gerade entdeckt, dass ich noch ein Problem habe. Und zwar:
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass<ValueT>
{
  public ValueT Value { get; set; }

  // usw.
}

// ...

var mv = new MyClass<int>();
mv.Value = 10;

var mr = new MyClass<string>();
mr.Value = null; // <- soll verhindert werden.
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass<ValueT>
{
public ValueT Value { get; set; }

// usw.
}

// ...

var mv = new MyClass<int>();
mv.Value = 10;

var mr = new MyClass<string>();
mr.Value = null; // <- soll verhindert werden.
C# Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass<ValueT>
{
  public ValueT Value { get; set; }

  // usw.
}

// ...

var mv = new MyClass<int>();
mv.Value = 10;

var mr = new MyClass<string>();
mr.Value = null; // <- soll verhindert werden.

Bisschen schwer, wenn ich mich nicht auf Referenztypen einschränken möchte beim Generic-Typ. Ach, ich vermisse meine Templates aus C++ :D

Grüssli

_________________
Danke für die Hilfe, Antwort oder Meinung!
C++: Std-Lib Referenz
C# .Net: MSDN kennt die Antwort
C/C++ Forum :: C# und .NET ::  Properties vor null Zuweisung schützen   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.