2017-02-10 1 views
0

Ich habe einen Code-Block, der einige Daten aus einer gespeicherten Prozedur erhält. Nachdem ich die Daten erhalten habe, möchte ich den Wert abhängig von den Bedingungen "isExisting" zuweisen. Ich möchte "isExisting" zum Zeitpunkt der Deklaration keinen Wert zuweisen.Verwendung von nicht zugewiesenen lokalen Variablen bei Verwendung eines foreach-Schleife

bool isExisting; 
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString())) 
{ 
    conn.Open(); 
    using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn)) 
    { 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add(new SqlParameter("input", value)); 
     using (var adapter = new SqlDataAdapter(cmd)) 
     { 
      DataSet ds = new DataSet(); 
      adapter.Fill(ds); 
      if (ds.Tables.Count > 0) 
      { 
       if (ds.Tables[0].Rows.Count == 0) 
        isExisting = false; 
       else 
       { 
        foreach (DataRow row in ds.Tables[0].Rows) 
        { 
         if (row["Key"].ToString() == ValueToCompareWith) 
         { 
          isExisting = true; 
          break; 
         } 
         else 
          isExisting = false; 
        } 
       } 

      } 
      else 
       isExisting = false; 
     } 
    } 
} 
if (!isExisting) //Step :getting error "use of unassigned local variable" 
{ 
} 

Ich glaube, ich bedeckt habe jede Bedingung und die Variable „isExisting“ einen Wert haben, wenn es „Schritt“ erreicht, aber noch erhalte ich Compiler-Fehler.

Das Problem begann becuase mein Code-Review-Tool ist ein Kommentar

„Ein toter Speicher geschieht werfen, wenn eine lokale Variable ein Wert zugewiesen wird, der nicht durch eine nachfolgende Anweisung gelesen wird. Die Berechnung oder einen Wert nur dann abrufen überschreiben oder wegwerfen, könnte einen schwerwiegenden Fehler im Code anzeigen. Auch wenn es kein Fehler ist, ist es bestenfalls eine Verschwendung von Ressourcen. Daher sollten alle berechneten Werte verwendet werden. "
Nicht kompatibel Codebeispiel

void CalculateRate(int a, int b) 
{ 
    int i; 

    i = a + b; // Noncompliant; calculation result not used before value is overwritten 
    i = DoSomething(); // Noncompliant; retrieved value not used 
    for (i = 0; i < 10; i++) 
    { 
    // ... 
    } 
    // ... 
} 

Antwort

1

Wie andere darauf hingewiesen haben, ist der Compiler nicht schlau genug, um zu wissen, ob Sie der Variablen tatsächlich einen Wert zuweisen.

können Sie diese Mehrdeutigkeit beheben, und Ihr Code aufzuräumen viel, unter Verwendung von etwas Linq:

bool isExisting; 
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString())) 
{ 
    conn.Open(); 
    using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn)) 
    { 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Parameters.Add(new SqlParameter("input", value)); 
     using (var adapter = new SqlDataAdapter(cmd)) 
     { 
      DataSet ds = new DataSet(); 
      adapter.Fill(ds); 

      isExisting = ds.Tables 
       .OfType<DataTable>() 
       .Take(1) 
       .SelectMany(t => t.Rows.OfType<DataRow>()) 
       .Any(r => r["Key"].ToString() == ValueToCompareWith); 
     } 
    } 
} 
if (!isExisting) 
{ 
} 

Ein weiterer Ansatz, um die isExisting Prüfung auf ein separates Verfahren zur ausklammern wäre:

bool CheckIsExisting(object value, string valueToCompareWith) 
{ 
    using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString())) 
    { 
     conn.Open(); 
     using (SqlCommand cmd = new SqlCommand("some_stored_procedure", conn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add(new SqlParameter("input", value)); 
      using (var adapter = new SqlDataAdapter(cmd)) 
      { 
       DataSet ds = new DataSet(); 
       adapter.Fill(ds); 
       if (ds.Tables.Count != 0 && ds.Tables[0].Rows.Count != 0) 
       { 
        foreach (DataRow row in ds.Tables[0].Rows) 
        { 
         if (row["Key"].ToString() == ValueToCompareWith) 
         { 
          return true; 
         } 
        } 
       } 
      } 
     } 
    } 

    return false; 
} 

Dann tun:

if (!CheckIsExisting(value, ValueToCompareWith)) 
{ 
    // do something... 
}   
1

Der Compiler ist ein Einfaltspinsel. Es überprüft nicht die gesamte Logik, um sicherzustellen, dass die Variable immer einen Wert erhält. Das ist nicht seine Aufgabe. Geben Sie einfach isExisting einen Standardwert ein, um den Compiler glücklich zu machen, und Ihr realer Code wird sowieso den richtigen Wert einstellen (wie Sie bereits gesagt haben).

+0

Mein Code-Review-Tool sagt, dass ich den Wert nicht deklarieren und zuweisen sollte, und der Compiler ist nicht in der Lage, herauszufinden, dass zur Laufzeit der Wert da sein wird. Also bin ich gestrandet. – Rajat

+1

Sind Sie sicher, dass dies in Ihrem Code-Review-Tool steht? Es ist so ziemlich das Gegenteil von Best Practice ... – John3136

+0

Stimmen Sie mit @ John3136 überein. Es empfiehlt sich, den Standardwert für jede Variable festzulegen, die Sie im Programm erstellen. –

1

Compiler können nicht sicher wissen, ob jedes Stück Code wird getroffen zu werden - zum Beispiel, wenn es keine Zeilen in dieser Schleife sein könnte:

foreach (DataRow row in ds.Tables[0].Rows) 

so deshalb, dass ganze, wenn Block nicht sein schlagen.

Legen Sie eine Standardeinstellung fest.

+0

Ich habe eine Anzahl von Zeilen gezählt, also habe ich von Basen bedeckt. Der Punkt ist Compiler ist nicht in der Lage zu verstehen, dass ich alle möglichen Fälle abgedeckt habe. – Rajat

+1

Warum das grundlegende Problem mit dem Setzen des Defaultwertes? Im Speicher ist technisch der Standardwert (bool) falsch. Es ist also besser, es als falsch zu initialisieren. Wenn Sie wirklich ein "weder wahr noch falsch" benötigen, verwenden Sie eine Nullable oder Kurzschrift "bool?" und setze es auf null. –

0

Standardwert von Bool ist false .Provide es in Ihrem Code.

bool isExisting=false; 

Ihre gesamte Business-Logik in den Code geschrieben sollten darauf achten, für

if (!isExisting) { 
} 

Haupt Logik hinter sich Compiler kaum stören, was Sie scripted .Es nur den zugewiesenen Wert wollen, bevor sie in jeder Situation nutzen können machen .

Siehe here, um mehr zu verstehen.

Verwandte Themen