Domanda

Salve, ho un DataRow estratto da una DataTable da un DataSet. Sto accedendo a una colonna definita in SQL come tipo di dati float. Sto cercando di assegnare quel valore a una variabile locale (tipo di dati float c #) ma sto ottenendo un InvalidCastExecption

DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];  

Ora, giocando con questo, l'ho fatto funzionare, ma non aveva alcun senso e non mi sembrava giusto.

_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];

Qualcuno può spiegare cosa mi sto perdendo qui?

È stato utile?

Soluzione

Un float SQL è un doppio secondo la documentazione per SQLDbType .

Altri suggerimenti

Un float in SQL è un Double nel CLR (C # / VB). C'è una tabella di tipi di dati SQL con gli equivalenti CLR su MSDN.

E normalmente non vorrai mai usare float in SQL Server (o reale) se prevedi di eseguire calcoli matematici sui dati in quanto è un tipo di dati inesatto e introdurrà errori di calcolo. Usa invece un tipo di dati decimale se hai bisogno di precisione.

Il float in Microsoft SQL Server equivale a un Double in C #. La ragione di ciò è che un numero in virgola mobile può approssimare solo un numero decimale, la precisione di un numero in virgola mobile determina la precisione con cui quel numero approssima un numero decimale. Il tipo Double rappresenta un numero a virgola mobile a 64 bit a doppia precisione con valori che vanno da negativo 1.79769313486232e308 a positivo 1.79769313486232e308, nonché zero positivo o negativo, PositiveInfinity, NegativeInfinity e Not-a-Number (NaN).

Penso che alla domanda principale sia stata data una risposta qui, ma mi sento in dovere di aggiungere qualcosa per la sezione della domanda che afferma che funziona.

  

_AccelLimit = (float) (double) esercizio [" DefaultAccelLimit "];

Il motivo per cui questo "funziona" e il motivo per cui "non si sente bene" è che stai eseguendo il downgrade del double a float dal secondo cast (quello a sinistra), quindi stai perdendo precisione e in modo efficace dicendo al compilatore che è ok per troncare il valore restituito.

In parole questa riga afferma ... Ottieni un oggetto (in questo caso può contenere un doppio) Trasforma l'oggetto in un doppio (perdendo tutto il wrapping dell'oggetto) Lancia il doppio su un float (perdendo tutta la precisione del doppio)

es. Se il valore è detto ,0124022806089461 e fai quanto sopra, il valore di AccelLimit sarà 0.01240228

poiché questa è l'estensione di ciò che un float in c # può ottenere dal doppio valore. È una cosa pericolosa da fare e sono abbastanza sicuro che sia un troncamento piuttosto che un arrotondamento, ma qualcuno potrebbe voler confermare questo perché non ne sono sicuro.

Il motivo per cui "non sembra giusto" è perché C # usa la stessa sintassi per unboxing e per casting , che sono due cose molto diverse. esercizio [" DefaultAccelLimit "] contiene un doppio valore, inscatolato come un oggetto. (double) è necessario per unbox l'oggetto in un doppio. Il (float) davanti a quello quindi lancia il doppio in un valore float. C # non consente il pugilato e il cast nella stessa operazione, quindi è necessario decomprimere, quindi trasmettere.

Lo stesso vale anche se il cast non è distruttivo. Se un float fosse inscatolato come un oggetto che volevi lanciare in un doppio, lo faresti in questo modo: (double) (float) object_var .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top