2012-03-16 20 views
12

Mamy pewien kod, który archiwizuje dane z bazy danych Microsoft Access do bazy danych MS SQL Server. Zakładając, że mamy już czytnik danych już wypełniony z tabeli Access i dodajemy parametr do SqlCommand w przygotowaniu do wstawienia, mamy typografię, która się nie udaje. Oto kod:Dlaczego ten rzut z krótkiej na int nie działa?

oSqlServerDbCmd_ForInsert.Parameters.AddWithValue("@Duration", 
    (int) oReader["Duration"]); 

Pole z oReadera jest w rzeczywistości liczbą całkowitą dostępu, która jest skrótem w języku C#. Jeśli rzucimy tutaj krótki, nie ma problemu. Jednakże, jeśli rzutujemy na int, kod generuje wyjątek InvalidCastException. Mogę błędnie odczytać to z MSDN documentation: "Istnieje predefiniowana niejawna konwersja z krótkiego na int, długiego, zmiennopozycyjnego, podwójnego lub dziesiętnego."

... ale wygląda na to, że to powinno zadziałać (moje rozumowanie polega na tym, że zdefiniowana jest niejawna konwersja, dlaczego wyraźna typografia nie działa?). Zdaję sobie sprawę, że obsada nie jest nawet konieczna, ponieważ AddWithValue akceptuje obiekt, więc faktycznie usunęliśmy obsadę z naszego kodu, ale chciałbym zobaczyć wyjaśnienie, dlaczego ta obsada nie działa, na wypadek gdybyśmy wpadli na coś takiego w przyszłość.

+1

dobry artykuł Eric Lippert na ten http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx –

+0

to nie jest odpowiedź na twoje pytanie, ale wygląda na to, że parametr '@ Duration' powinien mieć numeryczny typ danych, w którym to przypadku nie chcesz używać wartości ciągu w wywołaniu "AddWithValue". – phoog

+0

@phoog Edytowałem kod, aby usunąć tę konwersję, ponieważ jest to oderwanie od tego, na czym naprawdę polegało to pytanie. Krótka odpowiedź brzmi, że konwersja ciągu była w kodzie, kiedy go odziedziczyliśmy. Ponieważ działało, dopóki nie zmieniliśmy typu danych w źródłowym DB, nie mieliśmy powodu do zbadania kodu. Po zepsuciu i kopaniu zobaczyliśmy, że konwersja ciągów jest zbędna (chociaż nie jest problematyczna, wierzcie lub nie). –

Odpowiedz

18

To, co masz w swoich rękach, jest instancją unboxing. W szczególności, gdy rozpakowujesz, możesz tylko rozpakować do typu wartości, która była oryginalnie zapakowana; jeśli ten typ to A i rozpakowujesz do B, , nie ma znaczenia, czy niejawna konwersja z A na B istnieje (rozpakowywanie nadal się nie powiedzie).

Zobacz Eric Lippert's classic blog post na ten temat za wyjaśnienie.

+0

+1 Zawsze o tym zapominam. 'obiekt o = (krótki) 10; int i = (int) o; 'zawiedzie. –

+1

Ach, to ma sens. Więc, czy najpierw rzuciłem to jako krótkie, czy mogłem rzucić to jako int bez problemu? –

+1

@ awilson53: Dokładnie. – Jon

5

Trzeba oddać do bardzo specyficznego rodzaju, ponieważ jesteś unboxing - problemem jest to, że oReader["Duration"] zwraca object instancję:

short myShort = 42; 
object o = myShort; 
int myInt = (int)o; //fails 

To będzie sukces, jeśli oddasz z powrotem na krótko, potem do int:

(int) (short) oReader["Duration"] 
+0

Dzięki za opinię, +1 ... oboje odpowiedzieliście na moje pytanie, więc będę musiał iść z pierwszym napędem. –

Powiązane problemy