Co jest najgorsze w C# or.NET? [zamknięte]

Ostatnio pracowałem z obiektem DateTime i napisałem coś takiego:

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

Dokumentacja intellisense dla AddDays() mówi, że dodaje dzień do daty, czego nie ma - w rzeczywistości zwraca datę z dodanym dniem, więc musisz napisać to tak:

DateTime dt = DateTime.Now;
dt = dt.AddDays(1);
return dt; // tomorrow's date
Ten już mnie ugryzł wiele razy, więc pomyślałem, że przydałoby się skatalogować najgorsze C# gotchas.
 369
Author: MusiGenesis, 2008-10-27

30 answers

private int myVar;
public int MyVar
{
    get { return MyVar; }
}
Blammo. Aplikacja ulega awarii bez śladu stosu. To się zdarza cały czas.

(zwróć uwagę na duże litery MyVar zamiast małych liter myVar w getterze.)

 295
Author: Eric Z Beard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-13 07:37:08

Typ.GetType

/ Align = "left" / Type.GetType(string). Zastanawiają się, dlaczego działa to dla typów w ich własnym zestawieniu, a niektóre typy jak System.String, ale nie System.Windows.Forms.Form. Odpowiedź jest taka, że wygląda tylko w bieżącym montażu i w mscorlib.

Metody anonimowe

C # 2.0 wprowadził metody anonimowe, prowadzące do nieprzyjemnych sytuacji takich jak:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            ThreadStart ts = delegate { Console.WriteLine(i); };
            new Thread(ts).Start();
        }
    }
}

Co to wydrukuje? Cóż, to całkowicie zależy od harmonogram. Wydrukuje 10 numerów, ale prawdopodobnie nie wydrukuje 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 tego możesz się spodziewać. Problem polega na tym, że to zmienna i została przechwycona, a nie jej wartość w momencie tworzenia delegata. Można to łatwo rozwiązać za pomocą dodatkowej zmiennej lokalnej o odpowiednim zakresie:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            int copy = i;
            ThreadStart ts = delegate { Console.WriteLine(copy); };
            new Thread(ts).Start();
        }
    }
}

Odroczone wykonanie bloków iteratora

Ten "test jednostkowy biedaka" nie przejdzie-dlaczego nie?

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Test
{
    static IEnumerable<char> CapitalLetters(string input)
    {
        if (input == null)
        {
            throw new ArgumentNullException(input);
        }
        foreach (char c in input)
        {
            yield return char.ToUpper(c);
        }
    }

    static void Main()
    {
        // Test that null input is handled correctly
        try
        {
            CapitalLetters(null);
            Console.WriteLine("An exception should have been thrown!");
        }
        catch (ArgumentNullException)
        {
            // Expected
        }
    }
}

Odpowiedź jest taka, że kod w kodzie źródłowym CapitalLetters jest wykonywany dopiero po wywołaniu metody iteratora MoveNext().

Mam inne dziwactwa na mojej stronie brainteasers .

 248
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-27 19:47:12

Ponowne rzucanie WYJĄTKÓW

Gotcha, która przyciąga wielu nowych programistów, jest semantyką wyjątku re-throw.

Dużo czasu widzę kod podobny do następującego

catch(Exception e) 
{
   // Do stuff 
   throw e; 
}

Problem polega na tym, że usuwa ślad stosu i znacznie utrudnia diagnozowanie problemów, ponieważ nie można śledzić, skąd pochodzi wyjątek.

Poprawnym kodem jest polecenie throw bez args:

catch(Exception)
{
    throw;
}

Lub zawijanie wyjątku w inny i używanie wyjątku wewnętrznego do Pobierz oryginalny ślad stosu:

catch(Exception e) 
{
   // Do stuff 
   throw new MySpecialException(e); 
}
 191
Author: Sam Saffron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-23 01:20:16

Okno Zegarka Heisenberga

To może cię mocno ugryźć, jeśli robisz rzeczy z ładowaniem na żądanie, takie jak to:

private MyClass _myObj;
public MyClass MyObj {
  get {
    if (_myObj == null)
      _myObj = CreateMyObj(); // some other code to create my object
    return _myObj;
  }
}

Załóżmy, że masz jakiś kod gdzie indziej używając tego:

// blah
// blah
MyObj.DoStuff(); // Line 3
// blah

Teraz chcesz debugować swoją metodę CreateMyObj(). Więc umieściłeś punkt przerwania na linii 3 powyżej, z zamiarem wkroczenia do kodu. Tak na wszelki wypadek, umieścisz również punkt przerwania na linii powyżej, który mówi _myObj = CreateMyObj();, a nawet punkt przerwania wewnątrz CreateMyObj().

The kod uderza w punkt przerwania na linii 3. Wkrocz do kodu. Spodziewasz się wprowadzić kod warunkowy, ponieważ _myObj jest oczywiście null, prawda? Uh... więc... dlaczego pominął warunek i poszedł prosto do return _myObj?! Najedź myszką na _myObj... i rzeczywiście, to ma wartość! Jak to się stało?!

Odpowiedź jest taka, że Twoje IDE spowodowało, że uzyskało wartość, ponieważ masz otwarte okno "watch" - szczególnie okno" Autos " watch, które wyświetla wartości wszystkich zmienne / właściwości istotne dla bieżącej lub poprzedniej linii wykonania. Kiedy trafisz na swój punkt przerwania na linii 3, okno obserwacyjne zdecydowało, że będziesz zainteresowany poznaniem wartości MyObj - więc za kulisami, ignorując którykolwiek z punktów przerwania , poszło i obliczyło dla Ciebie wartość MyObj - łącznie z wywołaniem CreateMyObj(), które ustawia wartość _myObj!

Dlatego nazywam to okno zegarka Heisenberga - nie można obserwować wartości bez wpływa na to... :)

Mam cię!


Edit - uważam, że komentarz @ ChristianHayter zasługuje na włączenie do głównej odpowiedzi, ponieważ wygląda na skuteczne obejście tego problemu. Więc za każdym razem, gdy masz leniwą posesję...

Udekoruj swoją nieruchomość za pomocą [DebuggerBrowsable (DebuggerBrowsableState.Nigdy)] lub [DebuggerDisplay("")]. - Christian Hayter

 187
Author: Shaul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-10 06:40:27

Oto kolejny raz, który mnie dopadnie:

static void PrintHowLong(DateTime a, DateTime b)
{
    TimeSpan span = a - b;
    Console.WriteLine(span.Seconds);        // WRONG!
    Console.WriteLine(span.TotalSeconds);   // RIGHT!
}

Czas.Seconds {[6] } jest sekundową częścią timespan (2 minuty i 0 sekund ma wartość seconds równą 0).

Czas.TotalSeconds to cały czas mierzony w sekundach (2 minuty mają całkowitą wartość 120 sekund).

 141
Author: Jon B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-12 02:23:27

Wyciekła pamięć, bo nie odłączyłeś zdarzeń.

To nawet przyłapało starszych programistów, których znam.

Wyobraź sobie formularz WPF z wieloma rzeczami w nim, a gdzieś tam subskrybujesz wydarzenie. Jeśli nie zrezygnujesz z subskrypcji, cały formularz jest przechowywany w pamięci po zamknięciu i usunięciu odniesienia.

Wydaje mi się, że problemem, który widziałem było tworzenie DispatchTimer w formularzu WPF i subskrybowanie zdarzenia Tick, jeśli nie zrobisz -= na timerze twój formularz przecieka pamięć!

W tym przykładzie Twój kod teardown powinien mieć

timer.Tick -= TimerTickEventHandler;

Ten jest szczególnie trudny, ponieważ utworzyłeś instancję Dispatchtimera wewnątrz formularza WPF, więc pomyślałbyś, że będzie to wewnętrzne odniesienie obsługiwane przez proces zbierania śmieci... niestety DispatchTimer używa statycznej wewnętrznej listy subskrypcji i żądań usług w wątku UI, więc Referencja jest 'własnością' klasy statycznej.

 77
Author: Timothy Walters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-10 12:27:47

Może nie do końca, bo zachowanie jest napisane wyraźnie w MSDN, ale złamało mi kark raz, bo uznałem to za raczej nieintuicyjne:

Image image = System.Drawing.Image.FromFile("nice.pic");

Ten facet zostawia plik "nice.pic" zablokowany, dopóki obraz nie zostanie usunięty. W tym czasie miałem do czynienia z nim myślałem, że byłoby miło załadować ikony w locie i nie zdawałem sobie sprawy (na początku), że skończyłem z dziesiątkami otwartych i zablokowanych plików! Obraz śledzi, skąd załadował plik...

Jak to rozwiązać? Myślałem, że jeden liniowiec wystarczy. Spodziewałem się dodatkowego parametru dla FromFile(), ale nie miałem żadnego, więc napisałem to...
using (Stream fs = new FileStream("nice.pic", FileMode.Open, FileAccess.Read))
{
    image = System.Drawing.Image.FromStream(fs);
}
 60
Author: jdehaan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-15 11:53:15

Jeśli liczyć ASP.NET powiedziałbym, że cykl życia webforms jest dla mnie dość duży. Spędziłem niezliczone godziny debugowania źle napisanego kodu formularzy internetowych, tylko dlatego, że wielu programistów po prostu nie rozumie, kiedy użyć które zdarzenie obsługi (ja w tym, niestety).

 50
Author: Erik van Brakel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-27 22:35:16

Overloaded = = operatory i nietypowe kontenery (arraylists, datasets, etc.):

string my = "my ";
Debug.Assert(my+"string" == "my string"); //true

var a = new ArrayList();
a.Add(my+"string");
a.Add("my string");

// uses ==(object) instead of ==(string)
Debug.Assert(a[1] == "my string"); // true, due to interning magic
Debug.Assert(a[0] == "my string"); // false
Rozwiązania?
  • Zawsze używaj string.Equals(a, b) podczas porównywania typów łańcuchów

  • Używając generyków, takich jak List<string>, aby upewnić się, że oba operandy są ciągami.

 47
Author: Jimmy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-16 03:19:15

DateTime.ToString ("dd/MM/RRRR") ; to w rzeczywistości nie zawsze daje dd/MM/RRRR, ale zamiast tego bierze pod uwagę ustawienia regionalne i zastępuje separator daty w zależności od tego, gdzie jesteś. Więc możesz dostać dd-MM-RRRR lub coś podobnego.

Dobrym sposobem na to jest użycie DateTime.ToString ("dd" / " MM " / "yyyy");


DateTime.ToString ("r") ma konwertować do RFC1123, który używa GMT. GMT znajduje się w ułamek sekundy od UTC, a mimo to specyfikacja formatu" r " nie konwertuje NA UTC , nawet jeśli dana DateTime jest określona jako lokalna.

Daje to następujący wynik (różni się w zależności od tego, jak daleko jest Twój czas lokalny od UTC):

DateTime.Parse("Tue, 06 Sep 2011 16:35:12 GMT").ToString("r")
>              "Tue, 06 Sep 2011 17:35:12 GMT"
UPS!
 45
Author: romkyns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-06 17:08:37
[Serializable]
class Hello
{
    readonly object accountsLock = new object();
}

//Do stuff to deserialize Hello with BinaryFormatter
//and now... accountsLock == null ;)

Morał historii : inicjalizatory pola nie są uruchamiane podczas deserializacji obiektu

 43
Author: Nicolas Dorier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-04 11:13:07

Widziałem ten jeden wysłany niedawno, i myślę, że jest dość niejasne, i bolesne dla tych, którzy nie wiedzą

int x = 0;
x = x++;
return x;

Ponieważ zwróci 0, a nie 1, Jak większość by się spodziewała

 42
Author: Mitchel Sellers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-27 19:35:34

Jestem trochę spóźniona na tę imprezę, ale mam dwa Gotcha, które mnie ostatnio ugryzły:

Rozdzielczość DateTime

Właściwość kleszcze mierzy czas w 10 milionowych częściach sekundy( bloki 100 nanosekund), jednak rozdzielczość nie jest 100 nanosekund, to około 15ms.

Ten kod:

long now = DateTime.Now.Ticks;
for (int i = 0; i < 10; i++)
{
    System.Threading.Thread.Sleep(1);
    Console.WriteLine(DateTime.Now.Ticks - now);
}

Da ci wyjście (na przykład):

0
0
0
0
0
0
0
156254
156254
156254

Podobnie, jeśli spojrzeć na DateTime.Teraz.Milisekundy, otrzymasz wartości w zaokrąglonych kawałkach 15.625 ms: 15, 31, 46 itd.

To szczególne zachowanie różni się w zależności od systemu, ale w tym API daty/czasu są inne Gotcha związane z rozdzielczością.


Ścieżka.Połącz

Świetny sposób na łączenie ścieżek plików, ale nie zawsze zachowuje się tak, jak można się spodziewać.

Jeśli drugi parametr zaczyna się znakiem \, nie da Ci pełnej ścieżki:

Ten kod:

string prefix1 = "C:\\MyFolder\\MySubFolder";
string prefix2 = "C:\\MyFolder\\MySubFolder\\";
string suffix1 = "log\\";
string suffix2 = "\\log\\";

Console.WriteLine(Path.Combine(prefix1, suffix1));
Console.WriteLine(Path.Combine(prefix1, suffix2));
Console.WriteLine(Path.Combine(prefix2, suffix1));
Console.WriteLine(Path.Combine(prefix2, suffix2));

Daje wynik:

C:\MyFolder\MySubFolder\log\
\log\
C:\MyFolder\MySubFolder\log\
\log\
 39
Author: Damovisa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:31

Po uruchomieniu procesu (za pomocą systemu.Diagnostyka), który zapisuje się do konsoli, ale nigdy nie czyta się konsoli.Out stream, po pewnej ilości danych wyjściowych aplikacja pojawi się zawiesić.

 37
Author: user25306,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-27 20:58:07

Brak skrótów operatorów w Linq-To-Sql

Zobacz tutaj .

Krótko mówiąc, wewnątrz klauzuli warunkowej zapytania Linq-to-Sql, nie można używać skrótów warunkowych, takich jak || i &&, aby uniknąć wyjątków od null; Linq-to-Sql ocenia obie strony operatora OR or I nawet jeśli pierwszy warunek eliminuje potrzebę oceny drugiego warunku!

 34
Author: Shaul Behr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:56

Używanie domyślnych parametrów z metodami wirtualnymi

abstract class Base
{
    public virtual void foo(string s = "base") { Console.WriteLine("base " + s); }
}

class Derived : Base
{
    public override void foo(string s = "derived") { Console.WriteLine("derived " + s); }
}

...

Base b = new Derived();
b.foo();

Wyjście:
baza pochodna

 28
Author: BlueRaja - Danny Pflughoeft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-14 20:21:17

Obiekty wartości w kolekcjach zmiennych

struct Point { ... }
List<Point> mypoints = ...;

mypoints[i].x = 10;

Nie działa.

mypoints[i] zwraca kopię obiektu Point value. C# pozwala na modyfikację pola kopii. Po cichu nic nie robiąc.


Aktualizacja: W C# 3.0 można to naprawić:

Cannot modify the return value of 'System.Collections.Generic.List<Foo>.this[int]' because it is not a variable
 27
Author: Bjarke Ebert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 14:40:45

Może nie najgorszy, ale niektóre części. NET framework używają stopni podczas gdy inne używają radianów (i dokumentacja, która pojawia się w Intellisense nigdy nie mówi, która, musisz odwiedzić MSDN, aby się dowiedzieć)

Tego wszystkiego można było uniknąć, mając zamiast tego klasę Angle...

 25
Author: BlueRaja - Danny Pflughoeft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-31 20:46:14

Dla programistów C/C++ przejście na C# jest naturalne. Jednak największą zaletą, na jaką natknąłem się osobiście (i widziałem, jak inni dokonują tego samego przejścia), jest nie do końca zrozumienie różnicy między klasami i strukturami w C#.

W C++ klasy i struktury są identyczne; różnią się one tylko domyślną widocznością, gdzie klasy domyślnie mają prywatną widoczność i struktury domyślnie mają publiczną widoczność. W C++ definicja klasy

    class A
    {
    public:
        int i;
    };

Jest funkcjonalnie równoważna tej definicji struktury.

    struct A
    {
        int i;
    };

W C# klasy są typami odniesienia, podczas gdy struktury są typami wartości. To sprawia, że duża różnica w (1) decydowaniu, kiedy użyć jednego nad drugim, (2) testowaniu równości obiektów, (3) wydajności (np. Boks/unboxing), itp.

W sieci znajdują się wszelkiego rodzaju informacje związane z różnicami między nimi (np. tutaj ). Gorąco zachęcam wszystkich do przejścia na C # do at najmniej mieć praktyczną wiedzę o różnicach i ich konsekwencjach.

 22
Author: Matt Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-12 21:36:56

Garbage collection and Dispose (). Chociaż nie musisz nic robić, aby zwolnić Pamięć, nadal musisz zwolnić zasoby poprzez Dispose(). Jest to niezwykle łatwa rzecz do zapomnienia, gdy używasz WinForms lub śledzisz obiekty w jakikolwiek sposób.

 19
Author: Jeff Kotula,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-27 20:07:11

Zakres zmiennych pętli Foreach!

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());

Wyświetla pięć "amet" , podczas gdy poniższy przykład działa dobrze

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());
 18
Author: Brian J Cardiff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-27 21:11:24

MS SQL Server nie radzi sobie z datami przed 1753 rokiem. Co istotne, jest to poza synchronizacją ze stałą. net DateTime.MinDate, która wynosi 1/1/1. Więc jeśli spróbujesz uratować umysł, zniekształconą datę (jak ostatnio zdarzyło mi się w imporcie danych) lub po prostu datę urodzenia Wilhelma Zdobywcy, będziesz w tarapatach. Nie ma wbudowanego obejścia tego problemu; jeśli prawdopodobnie będziesz musiał pracować z datami przed 1753 rokiem, musisz napisać własne obejście.

 18
Author: Shaul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 13:31:33

Implementacja tablic IList

Ale nie wdrażaj tego. Kiedy wywołujesz Add, mówi ci, że to nie działa. Dlaczego więc klasa implementuje interfejs, skoro nie może go obsługiwać?

Kompiluje, ale nie działa:

IList<int> myList = new int[] { 1, 2, 4 };
myList.Add(5);

Mamy ten problem dużo, ponieważ serializer (WCF) zamienia wszystkie Ilisty w tablice i dostajemy błędy uruchomieniowe.

 17
Author: Stefan Steinegger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 15:02:20

Kontrakt na żywo.Przeczytane to coś, co widziałem wiele osób:

// 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);

Powodem tego błędu jest to, że Stream.Read odczyta co najwyżej określoną liczbę bajtów, ale jest całkowicie wolna, Aby odczytać tylko 1 bajt, nawet jeśli przed końcem strumienia dostępne są kolejne 7 bajtów.

Nie pomaga to, że wygląda tak podobnie do Stream.Write, Które jest gwarantowane, że wszystkie bajty zostaną zapisane, jeśli powróci bez wyjątku. To także nie pomaga to, że powyższy kod działa prawie cały czas . I oczywiście nie pomaga to, że nie ma gotowej, wygodnej metody do poprawnego odczytu dokładnie N bajtów.

Tak więc, aby zatkać dziurę i zwiększyć świadomość tego, oto przykład poprawnego sposobu, aby to zrobić:]}
    /// <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;
    }
 17
Author: Roman Starkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-28 22:45:49

The Nasty Linq Caching Gotcha

Zobacz moje pytanie , które doprowadziło do tego odkrycia i blogera , który odkrył problem.

Krótko mówiąc, DataContext przechowuje pamięć podręczną wszystkich obiektów Linq-to-Sql, które kiedykolwiek załadowałeś. Jeśli ktoś inny wprowadzi jakiekolwiek zmiany do rekordu, który wcześniej załadowałeś, nie będziesz w stanie uzyskać najnowszych danych, nawet jeśli jawnie przeładujesz rekord!

Jest to spowodowane właściwością o nazwie ObjectTrackingEnabled Na DataContext, który domyślnie jest true. Jeśli ustawisz tę właściwość na false, rekord będzie ładowany od nowa za każdym razem... ale ... nie można utrzymywać żadnych zmian w tym rekordzie za pomocą SubmitChanges ().

Mam cię!

 17
Author: Shaul Behr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:54

Wydarzenia

Nigdy nie rozumiałem, dlaczego wydarzenia są cechą językową. Są one skomplikowane w użyciu: musisz sprawdzić, czy nie ma null przed wywołaniem, musisz się wyrejestrować( samodzielnie), nie możesz dowiedzieć się, kto jest zarejestrowany (np.). Dlaczego wydarzenie nie jest tylko klasą w bibliotece? W zasadzie wyspecjalizowany List<delegate>?

 14
Author: Stefan Steinegger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 12:44:42

Enumerable mogą być oceniane więcej niż raz

Ugryzie cię, gdy będziesz miał leniwie wyliczone wyliczenia i powtórzysz je dwa razy i uzyskasz różne wyniki. (lub otrzymujesz te same wyniki, ale niepotrzebnie wykonuje dwa razy)

Na przykład, pisząc pewien test, potrzebowałem kilku plików tymczasowych, aby przetestować logikę:

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName());

foreach (var file in files)
    File.WriteAllText(file, "HELLO WORLD!");

/* ... many lines of codes later ... */

foreach (var file in files)
    File.Delete(file);

Wyobraź sobie moje zaskoczenie, kiedy File.Delete(file) rzuca FileNotFound!!

To, co się tutaj dzieje, to to, że files wyliczenie ma iteracja dwa razy (wyniki z pierwszej iteracji są po prostu zapamiętane, a nie ) i przy każdej nowej iteracji będziesz ponownie wywoływać Path.GetTempFilename(), więc otrzymasz inny zestaw tymczasowych nazw plików.

Rozwiązaniem jest oczywiście wyliczenie wartości za pomocą ToArray() lub ToList():

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName())
    .ToArray();

To jest jeszcze straszniejsze, gdy robisz coś wielowątkowego, jak:

foreach (var file in files)
    content = content + File.ReadAllText(file);

I dowiadujesz się content.Length jest nadal 0 po wszystkich zapisach!! Następnie zaczynasz rygorystycznie sprawdza, że nie masz stanu wyścigowego, kiedy.... po zmarnowanej godzinie... domyśliłeś się, że to tylko ta mała rzecz, o której zapomniałeś....

 13
Author: chakrit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-28 14:17:52

Właśnie znalazłem dziwną, przez którą utknąłem na chwilę w debugowaniu:

Można zwiększyć wartość NULL dla nullable int bez rzucania ekscesji, a wartość pozostaje null.

int? i = null;
i++; // I would have expected an exception but runs fine and stays as null
 13
Author: DevDave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-14 14:53:21

Dzisiaj naprawiłem błąd, który wymykał się przez długi czas. Błąd był w klasie generycznej, która była używana w scenariuszu wielowątkowym, a statyczne pole int było używane do zapewnienia synchronizacji bez blokady za pomocą Interlocked. Błąd został spowodowany, ponieważ każda instancja klasy generycznej dla typu ma swoją statykę. Więc każdy wątek ma swoje własne pole statyczne i nie był używany zamek zgodnie z przeznaczeniem.

class SomeGeneric<T>
{
    public static int i = 0;
}

class Test
{
    public static void main(string[] args)
    {
        SomeGeneric<int>.i = 5;
        SomeGeneric<string>.i = 10;
        Console.WriteLine(SomeGeneric<int>.i);
        Console.WriteLine(SomeGeneric<string>.i);
        Console.WriteLine(SomeGeneric<int>.i);
    }
}

To drukuje 5 10 5

 13
Author: Pratik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-20 09:49:00
TextInfo textInfo = Thread.CurrentThread.CurrentCulture.TextInfo;

textInfo.ToTitleCase("hello world!"); //Returns "Hello World!"
textInfo.ToTitleCase("hElLo WoRld!"); //Returns "Hello World!"
textInfo.ToTitleCase("Hello World!"); //Returns "Hello World!"
textInfo.ToTitleCase("HELLO WORLD!"); //Returns "HELLO WORLD!"
Tak, to zachowanie jest udokumentowane, ale to z pewnością nie czyni tego dobrym.
 9
Author: BlueRaja - Danny Pflughoeft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-30 01:24:33