384 Stimmen

Was ist der schlimmste Fehler in C# oder .NET?

Ich habe kürzlich mit einem DateTime Objekt, und schrieb etwas wie dieses:

DateTime dt = DateTime.Now;
dt.AddDays(1);
return dt; // still today's date! WTF?

Die Intellisense-Dokumentation für AddDays() sagt, dass es einen Tag zum Datum hinzufügt, was nicht der Fall ist - es devuelve ein Datum mit einem hinzugefügten Tag, also müssen Sie es so schreiben:

DateTime dt = DateTime.Now;
dt = dt.AddDays(1);
return dt; // tomorrow's date

Dies hat mich schon einige Male gebissen, also dachte ich, es wäre nützlich, die schlimmsten C#-Fehler zu katalogisieren.

158 Stimmen

Return DateTime.Now.AddDays(1);

24 Stimmen

Soweit ich weiß, sind die eingebauten Werttypen alle unveränderlich, zumindest insofern, als jede Methode, die mit dem Typ verbunden ist, ein neues Element zurückgibt, anstatt das vorhandene Element zu verändern. Zumindest fällt mir spontan kein Typ ein, der dies nicht tut: alles schön und konsistent.

1 Stimmen

Community-Wiki, so viel Spam in SO jetzt. Wenn Fragen subjektiv sind (keine endgültige Antwort), sollte es Community Wiki sein.

1voto

Shaul Behr Punkte 35201

LinqToSQL und das Aggregat der leeren Menge

Véase diese Frage .

Wenn Sie eine LinqToSql-Abfrage haben, auf der Sie ein Aggregat ausführen - wenn Ihre Ergebnismenge leer ist, kann Linq nicht herausfinden, was der Datentyp ist, auch wenn er deklariert wurde.

z.B. Angenommen, Sie haben eine Tabelle Claim mit einem Feld Amount , die in LinqToSql vom Typ decimal .

var sum = Claims.Where(c => c.ID < 0).Sum(c => c.Amount);

Offensichtlich gibt es keine Ansprüche mit einer ID kleiner als Null, so dass Sie erwarten würden, dass sum = null ist, richtig? Falsch! Sie erhalten eine InvalidOperationException weil die SQL-Abfrage, die der Linq-Abfrage zugrunde liegt, keinen Datentyp hat. Sie müssen Linq ausdrücklich mitteilen, dass es sich um eine Dezimalzahl handelt! Daher:

var sum = Claims.Where(c => c.ID < 0).Sum(c => (decimal?)c.Amount);

Das ist wirklich dumm und IMO ein Designfehler von Microsoft.

GOTCHA!

1voto

NotMe Punkte 86089

Das Folgende wird die Ausnahme in .Net nicht abfangen. Stattdessen führt es zu einer StackOverflow-Ausnahme.

private void button1_Click( object sender, EventArgs e ) {
    try {
        CallMe(234);
    } catch (Exception ex) {
        label1.Text = ex.Message.ToString();
    }
}
private void CallMe( Int32 x ) {
    CallMe(x);
}

Für die Kommentatoren (und Downvotes):
Es wäre äußerst selten, dass ein Stapelüberlauf so offensichtlich ist. Wenn er jedoch auftritt, werden Sie die Ausnahme nicht abfangen und wahrscheinlich mehrere Stunden damit verbringen, das Problem genau zu finden. Erschwerend kommt hinzu, dass der SO in wenig genutzten Logikpfaden auftritt, insbesondere bei einer Webanwendung, bei der Sie die genauen Bedingungen, die das Problem ausgelöst haben, möglicherweise nicht kennen.

Dies ist genau die gleiche Situation wie bei der akzeptierten Antwort auf diese Frage ( https://stackoverflow.com/a/241194/2424 ). Die Eigenschaft getter auf diese Antwort ist im Wesentlichen genau das gleiche tun, wie der obige Code und Absturz ohne Stack-Trace.

1voto

tvanfosson Punkte 506878
mystring.Replace("x","y")

Während es aussieht, wie es die Ersetzung auf die Zeichenfolge tun sollte es auf aufgerufen wird, gibt es tatsächlich eine neue Zeichenfolge mit den Ersetzungen gemacht, ohne die Zeichenfolge zu ändern es auf aufgerufen wird. Sie müssen bedenken, dass Strings unveränderlich sind.

0voto

Shaul Behr Punkte 35201

Linq2SQL: Das Mapping von Interface Member [...] wird nicht unterstützt.

Wenn Sie eine Linq2Sql-Abfrage auf ein Objekt ausführen, das eine Schnittstelle implementiert, erhalten Sie ein sehr merkwürdiges Verhalten. Nehmen wir an, Sie haben eine Klasse MyClass die eine Schnittstelle implementiert IHasDescription also:

public interface IHasDescription {
  string Description { get; set; }
}

public partial class MyClass : IHasDescription { }

(Die andere Hälfte der MyClass ist eine von Linq2Sql generierte Klasse, die die Eigenschaft Description .)

Nun schreiben Sie etwas Code (normalerweise geschieht dies in einer generischen Methode):

public static T GetByDescription<T>(System.Data.Linq.Table<T> table, string desc) 
  where T : class, IHasDescription {
  return table.Where(t => t.Description == desc).FirstOrDefault();
}

Kompiliert gut - aber Sie erhalten einen Laufzeitfehler:

NotSupportedException: The mapping of interface member IHasDescription.Description is not supported.

Was kann man dagegen tun? Nun, das ist eigentlich ganz einfach: Ändern Sie einfach Ihre == à .Equals() also:

return table.Where(t => t.Description.Equals(desc)).FirstOrDefault();

Und jetzt funktioniert alles einwandfrei!

Véase aquí .

0voto

Shaul Behr Punkte 35201

LinqToSql-Batches werden mit dem Quadrat der Batchgröße langsamer

Hier ist die Frage (und Antwort ), wo ich dieses Problem untersucht habe.

Kurz gesagt, wenn Sie versuchen, zu viele Objekte im Speicher anzuhäufen, bevor Sie DataContext.SubmitChanges() beginnen Sie, eine geometrische Trägheit zu erleben. Ich habe nicht zu 100 % bestätigt, dass dies der Fall ist, aber es scheint mir, dass der Aufruf von DataContext.GetChangeSet() veranlasst den Datenkontext, eine Äquivalenzbewertung durchzuführen ( .Equals() ) auf jede einzelne Kombination von 2 Elementen im Änderungssatz, wahrscheinlich um sicherzustellen, dass es nicht doppelt eingefügt wird oder andere Gleichzeitigkeitsprobleme verursacht. Das Problem ist, dass bei sehr großen Stapeln die Anzahl der Vergleiche proportional mit dem Quadrat von n d.h. (n^2+n)/2 . 1.000 Elemente im Speicher bedeuten über 500.000 Vergleiche ... und das kann verdammt lange dauern.

Um dies zu vermeiden, müssen Sie sicherstellen, dass Sie bei allen Stapeln, bei denen Sie eine große Anzahl von Artikeln erwarten, das Ganze innerhalb der Transaktionsgrenzen durchführen, indem Sie jeden einzelnen Artikel speichern, wenn er erstellt wird, und nicht in einem einzigen großen Speicher am Ende.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X