2012-03-16 79 views
12

我們有一些將數據從Microsoft Access數據庫歸檔到MS SQL Server數據庫的代碼。假設我們已經從Access表中填充了一個數據讀取器,並且我們正在向SqlCommand添加一個參數以準備插入,我們有一個失敗的類型轉換。下面是代碼:爲什麼從short到int失敗?

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

該字段從oReader實際上是一個訪問整數,它是在C#短路。如果我們在這裏投下一小部分就沒有問題了。但是,如果我們轉換爲int,則代碼將引發InvalidCastException。我可能會誤從MSDN documentation

「有從short到int,long,float,double或decimal的預定義隱式轉換。」

...但它聽起來像這應該工作(我的推理是,如果隱式轉換定義爲什麼明確的類型轉換不工作?)。我意識到演員陣容甚至是不必要的,因爲AddWithValue接受一個對象,所以我們實際上已經從我們的代碼中刪除了演員陣容,但我很想看到一個解釋,爲什麼這個演員陣容失敗了,以防萬一我們碰到這樣的情況未來。

+1

好文章這個http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx – 2012-03-16 17:32:21

+0

這不是一個回答您的問題,但它看起來像你的'@ Duration'參數應該有一個數字數據類型,在這種情況下,您不希望在「AddWithValue」調用中使用字符串值。 – phoog 2012-03-16 19:00:20

+0

@phoog我編輯了代碼來刪除該轉換,因爲這是對這個問題最終導致的問題的分心。簡短的回答是,當我們繼承它時,字符串轉換在代碼中。由於它在我們改變源數據庫中的數據類型之前一直在工作,所以我們沒有理由調查代碼。一旦它被破壞,我們挖掘出來,我們看到字符串轉換是不必要的(儘管沒有問題,不管信不信)。 – 2012-03-16 19:56:35

回答

18

你手上的東西是unboxing的一個實例。特別是在拆箱時,您只能取消裝箱到最初裝箱的值的類型;如果這種類型是A並且您要拆箱到B,,那麼從A到B的隱式轉換是否存在並不重要(拆箱仍然會失敗)

請參閱Eric Lippert的classic blog post關於此主題的相關說明。

+0

+1我總是忘記這一點。對象o =(短)10; int i =(int)o;'失敗。 – 2012-03-16 17:30:07

+1

啊,這是有道理的。那麼,我是否首先把它作爲一個短暫的東西,然後我可以把它作爲一個整數沒有問題? – 2012-03-16 17:31:41

+1

@ awilson53:的確如此。 – Jon 2012-03-16 17:32:10

5

你必須強制轉換爲非常特殊的,因爲你是拆箱 - 問題是,oReader["Duration"]返回object實例:

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

它會成功,如果你投回到短,再爲int:

(int) (short) oReader["Duration"] 
從埃裏克利珀上
+0

感謝您的反饋,+1 ...你們都回答了我的問題,所以我將不得不與先行者一起去。 – 2012-03-16 17:38:26