Prüfen Sie, ob Klasseneigenschaften nicht null / leer / zugewiesen wurden

78878
victor

Ich habe eine Klasse, die ich für die Anzeige auf einem Feldset einer Webseite verwende. Alle Eigenschaften dieser Klasse werden jedoch optional vom Benutzer ausgefüllt. Dies bedeutet, dass alle Eigenschaften den Wert null / default haben können. In diesem Fall möchte ich das Feldset überhaupt nicht rendern, statt ein leeres anzuzeigen.

Ich habe eine einfache isEmpty()Methode geschrieben, die alle Eigenschaftswerte mithilfe von Reflektion prüft. Ich fürchte jedoch, dass dies zu umfangreich werden kann.

public class User
{
    [Display(Name = "First Name:")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name:")]
    public string LastName { get; set; }

    public bool isEmpty()
    {
        Type t = this.GetType();

        var properties = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (var prop in properties)
        {
            var value = prop.GetValue(this, null);

            if (value != null && (string)value != "")
            {
                return false;
            }
        }

        return true;
    }
}

Das isEmpty()setzt natürlich voraus, dass alle Eigenschaften Strings sind.

Was denkst du? Wird dies potenziell expansiv, wenn die Klasse wächst?

Antworten
10
Nun, zu Beginn denke ich, ich würde lieber die Methode "IsEmpty" als "isEmpty" sehen. Dies ist gemäß der [Kapitalisierungsrichtlinie von Microsoft] (http://msdn.microsoft.com/de-de/library/ms229043%28v=vs.110%29.aspx). RubberDuck vor 5 Jahren 1
Ist das ASP.NET MVC 5? mjolka vor 5 Jahren 0

2 Antworten auf die Frage

11
Abbas

Benennung:

Verwenden Sie keine Variablennamen wie t. Sie sind nicht sinnvoll, nicht für Sie, nicht für andere. In diesem Fall verwenden Sie type.

Klassennamen, öffentliche Felder und Methodennamen verwenden PascalCaseund nicht camelCase. Also isEmptywerden IsEmpty. Andererseits ist dies auch kein sinnvoller Name. Boolesche Methoden oder Eigenschaften in C # beginnen höchstwahrscheinlich mit Isoder Has. Ein Beispiel für den Namen Ihrer Methode wäre HasAllEmptyProperties.

var Stichwort:

Verwenden Sie vardiese Option, um Ihre Variablen zu deklarieren, anstatt sie explizit zu deklarieren. Der Compiler bestimmt den Typ für Sie und Ihr Code sieht sauberer aus.

Die Methode:

Ihr Code sieht gut aus. Sie können es jedoch mit LinQ sauberer machen. Loops werden nicht vermieden, sehen aber sauberer aus. Ich sage nicht, dass dies eine perfekte Lösung ist, aber hier heißt es:

public bool HasAllEmptyProperties()
{
    var type = GetType();
    var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    var hasProperty = properties.Select(x => x.GetValue(this, null))
                                .Any(y => y != null && !String.IsNullOrWhiteSpace(y.ToString()));
    return !hasProperty;
}

Ich hätte auch die All()Methode und den positiven Vergleich verwenden können Any(). Dies ist jedoch ineffizient, da alle Elemente gegen die Bedingung geprüft werden müssen, und sie Any()werden zurückgegeben, sobald ein Element die Bedingung erfüllt (wie in Ihrer Schleife).

Sie können den Vergleichscode für eine Wiederverwendbarkeit in eine Erweiterungsmethode werfen. Es macht auch Ihren Methodencode sauberer, zum Beispiel:

public static class Extensions
{
    public static bool IsNullOrEmpty(this object obj)
    {
        return obj == null || String.IsNullOrWhiteSpace(obj.ToString());
    }
}

public bool HasAllEmptyProperties()
{
    var type = GetType();
    var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    var hasProperty = properties.Select(x => x.GetValue(this, null))
                                .Any(x => !x.IsNullOrEmpty());
    return !hasProperty;
}

Da Sie nur zwei Eigenschaften haben, ist Performace kein Problem. Selbst wenn Sie ein paar weitere Eigenschaften hinzufügen würden. Hoffe das hilft!

Danke für deine Antwort. Ich stimme mit Ihnen in Bezug auf den Variablennamen überein. Ich habe jedoch "t" für "Type" ausgewählt. Ich denke nicht, dass es in diesem speziellen Fall ein Problem ist, weil der Code wirklich klein ist (es ist keine Gewohnheit). Was das Styling angeht, so habe ich erst seit kurzem mit C # gearbeitet, und der Stil unterscheidet sich ein wenig von anderen mir bekannten Sprachen, und manchmal vermische ich sie. Danke, dass Sie darauf hingewiesen haben. In Bezug auf das var habe ich es verwendet. Ich habe "Type" beibehalten, da es einen Buchstaben länger ist. Es ist nicht wirklich Zeitersparnis, stattdessen "var" einzugeben. Hätte ich var verwendet, hätte ich definitiv "type" anstelle von "t" genannt. victor vor 5 Jahren 0
Über die Verwendung von LINQ stimme ich in diesem Fall nicht zu, dass der Code leichter lesbar ist. Ich denke, der Code sieht eher aus wie Code statt eines für Menschen lesbaren Textes (in diesem Fall wiederum). Die Erweiterungsmethode ist interessant, ich habe nie eine Erweiterungsmethode verwendet, ich werde mich darum kümmern; Dennoch wird diese Methode nur für diese Klasse verwendet und wird nicht von allen anderen verwendet. Ich denke, ich werde das überspringen :) Vielen Dank für Ihre Bewertung. Ich habe gerade überprüft, LINQ wäre wahrscheinlich langsamer als foreach. victor vor 5 Jahren 0
Wie gesagt, Ihr Code sieht gut aus, wie er ist. Die LinQ-Option war nur ein weiterer Weg, um das gleiche Ergebnis zu erzielen. Ich habe ziemlich viel damit gearbeitet, also ist es für mich sehr lesbar. Die Erweiterungsmethode mag in der Tat übertrieben sein, aber es ist eine nette Funktion und ich habe immer an Erweiterungen gedacht. Deshalb verwende ich oft (Erweiterungs-) Methoden. Abbas vor 5 Jahren 1
4
Jeroen Vannevel

Es sieht ziemlich hackig aus, weil ich das Gefühl habe, dass irgendwo in der Zeile irgendwo sein muss, wo man leichter feststellen kann, ob die Eigenschaften ausgefüllt sind oder nicht.

Trotzdem: Im stringsMoment wird Ihr Code nur funktionieren, während es wahrscheinlich realistisch ist zu sagen, dass es in Zukunft möglicherweise auch andere Felder gibt (Id, DateOfBirth usw.), die eine Codeänderung erfordern würden. Daher würde ich vorschlagen, Ihren Code etwas weniger string-spezifisch zu machen:

public bool isEmpty()
{
    var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (var prop in properties)
    {
        var value = prop.GetValue(this, null);

        if (value != default(prop.PropertyType))
        {
            return false;
        }

        var stringValue = value as string;
        if(stringValue != null)
        {
            if(stringValue != string.IsNullOrWhiteSpace(value))
            {
                return false;
            }
        }
    }

    return true;
}
  • Verwendung von defaultWörtern mit primitiven Typen (sie werden nicht in der Lage sein 0)
  • Wenn Sie möchten, können Sie 0sie als nullbare Typen definieren
  • as kombiniert mit != null
  • IsNullOrWhiteSpace(string) anstelle von leeren Anführungszeichen
  • Entfernt, tda es nur einmal verwendet wurde
Vielen Dank für den Stackoverflow-Link. Es sieht auch für mich hackig aus, deshalb habe ich es hier gepostet; Tatsache ist jedoch, dass es keinen Platz in der Zeile gibt, an dem die Requisiten einfacher zu prüfen wären, da ich alle prüfen muss. Ohne Reflexion gibt es keine Möglichkeit, zu wissen, welche Eigenschaften die Klasse hat, es sei denn durch harte Codierung them "x.name nicht null && x.lastname nicht null usw." ... schlägt isNullOrWhiteSpace auch für leere Zeichenfolge fehl? victor vor 5 Jahren 0
Ich dachte mir, vielleicht könnten Sie den `ModelState` irgendwo zusammen mit` [Required] `Attributen überprüfen, aber das hängt natürlich von Ihrer Situation ab. Ja, das ist der Fall (http://msdn.microsoft.com/de-de/library/system.string.isnullorwhitespace (v = vs.110) .aspx). Jeroen Vannevel vor 5 Jahren 1