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.

19voto

Jeff Kotula Punkte 2094

Garbage collection und Dispose(). Obwohl Sie nichts tun müssen, um Speicherplatz freizugeben Speicher müssen Sie noch frei werden Ressourcen über Dispose(). Dies ist eine Sache, die man leicht vergisst, wenn man WinForms verwendet oder Objekte in irgendeiner Weise verfolgt.

18voto

Shaul Behr Punkte 35201

Die unangenehme Linq Caching Gotcha

Véase meine Frage die zu dieser Entdeckung führten, und der Blogger der das Problem entdeckt hat.

Kurz gesagt, der DataContext speichert einen Cache aller Linq-to-Sql-Objekte, die Sie jemals geladen haben. Wenn jemand anderes Änderungen an einem Datensatz vornimmt, den Sie zuvor geladen haben, können Sie die neuesten Daten nicht mehr abrufen, auch wenn Sie den Datensatz explizit neu laden!

Der Grund dafür ist eine Eigenschaft namens ObjectTrackingEnabled auf den DataContext, was standardmäßig true ist. Wenn Sie diese Eigenschaft auf false setzen, wird der Datensatz jedes Mal neu geladen... BUT ... können Sie keine Änderungen an diesem Datensatz mit SubmitChanges() beibehalten.

GOTCHA!

18voto

Roman Starkov Punkte 55278

Der Vertrag auf Stream.Read ist etwas, das ich bei vielen Menschen beobachtet habe:

// Read 8 bytes and turn them into a ulong
byte[] data = new byte[8];
stream.Read(data, 0, 8); // <-- WRONG!
ulong data = BitConverter.ToUInt64(data);

Der Grund dafür, dass dies falsch ist, liegt darin, dass Stream.Read wird lesen allenfalls die angegebene Anzahl von Bytes, ist aber völlig frei nur 1 Byte zu lesen, auch wenn vor dem Ende des Streams noch 7 Bytes zur Verfügung stehen.

Es hilft auch nicht, dass es so ähnlich aussieht wie Stream.Write die es garantiert, dass er alle Bytes geschrieben hat, wenn er ohne Ausnahme zurückkehrt. Es hilft auch nicht, dass der obige Code funktioniert fast immer . Und natürlich hilft es auch nicht, dass es keine fertige, bequeme Methode gibt, um genau N Bytes korrekt zu lesen.

Um die Lücke zu schließen und das Bewusstsein für diese Problematik zu schärfen, hier ein Beispiel für eine korrekte Vorgehensweise:

    /// <summary>
    /// Attempts to fill the buffer with the specified number of bytes from the
    /// stream. If there are fewer bytes left in the stream than requested then
    /// all available bytes will be read into the buffer.
    /// </summary>
    /// <param name="stream">Stream to read from.</param>
    /// <param name="buffer">Buffer to write the bytes to.</param>
    /// <param name="offset">Offset at which to write the first byte read from
    ///                      the stream.</param>
    /// <param name="length">Number of bytes to read from the stream.</param>
    /// <returns>Number of bytes read from the stream into buffer. This may be
    ///          less than requested, but only if the stream ended before the
    ///          required number of bytes were read.</returns>
    public static int FillBuffer(this Stream stream,
                                 byte[] buffer, int offset, int length)
    {
        int totalRead = 0;
        while (length > 0)
        {
            var read = stream.Read(buffer, offset, length);
            if (read == 0)
                return totalRead;
            offset += read;
            length -= read;
            totalRead += read;
        }
        return totalRead;
    }

    /// <summary>
    /// Attempts to read the specified number of bytes from the stream. If
    /// there are fewer bytes left before the end of the stream, a shorter
    /// (possibly empty) array is returned.
    /// </summary>
    /// <param name="stream">Stream to read from.</param>
    /// <param name="length">Number of bytes to read from the stream.</param>
    public static byte[] Read(this Stream stream, int length)
    {
        byte[] buf = new byte[length];
        int read = stream.FillBuffer(buf, 0, length);
        if (read < length)
            Array.Resize(ref buf, read);
        return buf;
    }

18voto

Shaul Behr Punkte 35201

MS SQL Server kann keine Daten vor 1753 verarbeiten. Bezeichnenderweise ist das nicht synchron mit der .NET DateTime.MinDate Konstante, die 1/1/1 beträgt. Wenn Sie also versuchen, ein Mindate, ein falsches Datum (wie mir kürzlich bei einem Datenimport passiert ist) oder einfach das Geburtsdatum von Wilhelm dem Eroberer zu speichern, werden Sie in Schwierigkeiten geraten. Es gibt keine eingebaute Abhilfe für dieses Problem; wenn Sie mit Daten vor 1753 arbeiten müssen, müssen Sie eine eigene Abhilfe schreiben.

18voto

Brian J Cardiff Punkte 619

Foreach-Schleifen Variablen Geltungsbereich!

var l = new List<Func<string>>();
var strings = new[] { "Lorem" , "ipsum", "dolor", "sit", "amet" };
foreach (var s in strings)
{
    l.Add(() => s);
}

foreach (var a in l)
    Console.WriteLine(a());

druckt fünf "amet", während das folgende Beispiel gut funktioniert

var l = new List<Func<string>>();
var strings = new[] { "Lorem" , "ipsum", "dolor", "sit", "amet" };
foreach (var s in strings)
{
    var t = s;
    l.Add(() => t);
}

foreach (var a in l)
    Console.WriteLine(a());

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