“System.Int16”类型的对象无法转换为“System.Nullable”1[System.Int32] 类型

Posted

技术标签:

【中文标题】“System.Int16”类型的对象无法转换为“System.Nullable”1[System.Int32] 类型【英文标题】:Object of type 'System.Int16' cannot be converted to type 'System.Nullable`1[System.Int32] 【发布时间】:2018-06-13 16:38:23 【问题描述】:

我有一个从数据读取器的数据生成类类型列表的方法。

if (datareader != null && datareader .HasRows)

  Dictionary<string, PropertyInfo> pDict= GetPropertyDictionary<T>();
  var fields = GetFieldNames(datareader );
  while (datareader .Read())
  
    T myobj= new T();
    for (int index = 0; index < fields.Count; index++)
                            
      if (pDict.TryGetValue(fields[index], out PropertyInfo info))
      
        var val1 = datareader .GetValue(index);                                
        info.SetValue(myobj, (val1 == DBNull.Value) ? null : val1, null);
      
    
  

我有类属性,其中一些可以为空。

public string StudentName get; set; 
public decimal? percentage get; set; 
public int? StudentNumber get; set; 

代码适用于所有属性,除了 StudentNumber 是 int。

在上面的代码中,以下行抛出异常 “System.Int16”类型的对象无法转换为“System.Nullable`1[System.Int32]”类型

info.SetValue(myobj, (val1 == DBNull.Value) ? null : val1, null);

有什么办法可以解决这个问题?

【问题讨论】:

(val1 == DBNull.Value) ? null : (int?)val1 是否作为您的三元组工作? val1 的类型是 Int16 且不可为空,因此与第一个表达式中返回 null 设置的类型期望不匹配。 是的,它是三元的。仅当类型为 int? 时,我才会遇到此问题,否则它与小数一起使用?,日期时间?。 Conditional operator assignment with Nullable<value> types?的可能重复 @Priya:你是如何解决这个问题的?在我的情况下,所有类型也使用相同的方法 你好@user2782405。这是数据类型的问题。由于我在这里使用反射,我需要指定读取器从数据库返回的相同数据类型。在数据库中它是 smallint,我试图将它转换为 int。所以它失败了。 【参考方案1】:

出于多种原因,我不同意此代码,但要解决您当前的问题并回答您的问题,这是因为您无法将 Int16 显式转换为 Int32Nullable&lt;Int32&gt;int?

要实现这一点,您需要先将值转换为Int32,然后再转换为Nullable&lt;Int3&gt;

有更好的方法,但要弄清楚发生了什么并在这里修复这个错误......

info.SetValue(myobj, val1 == DBNull.Value ? null : (int?)Convert.ToInt32(val1), null);

【讨论】:

但我不能直接使用 (int?) 将其转换为整数。此方法通常用于所有类型,如字符串、整数、小数、日期、双精度等。我只遇到整数问题。 这正是我不同意这段代码的原因。它不能以多种方式使用,但答案只是为了澄清您的问题并修复该错误。 IMO,我相信您需要的是支持并重新考虑该过程,我的意思是我保证的友好。我不怀疑你的技能,所以不要把它当作打击。我只是觉得你想做的事情和你正在做的事情并不一致。此代码假设太多,并没有考虑您想要的通用行为。不过你做得很好,请不要反感地阅读这篇文章,我只是回答了具体问题 @Michale,不,不,我不会以消极的方式接受你的建议。我一定会重新考虑采取的方法,以提高效率。 :) 谢谢伙计。我当然是最好的,我很高兴你没有不高兴。【参考方案2】:

您在这里遇到的问题是,虽然您可以将 short 转换为 int,但您不能将已装箱的 short 直接转换为 int。即,

object box = (short)5;
var x = (int?)box; // Invalid cast.
var y = (int?)(short?)box; // fine, we cast to short and then to int.

您可以将您的类的属性类型更改为short?,或者您可以检查您的属性类型是否为Nullable&lt;int32&gt;,并在这种情况下对值使用Convert.ToInt32

【讨论】:

您能提出任何通用的解决方案吗?因为这个方法是为datareader中的每一列调用和执行的 @Priya 我想不出一个好的通用方法。您将不得不编写一些特定于类型的代码来处理特定于类型的转换。 我尝试了一件奇怪的事情,它奏效了。而不是简单的 int?,如果我使用 Int16?,即 public Int16?学生号 得到;放; ,它毫无例外地工作。为什么会这样! @Priya 出于我上面概述的原因。您可以从已装箱的Int16 转换为Int16?。您不能将已装箱的Int16 转换为Int32Int32?,而必须使用Convert.ToInt32 调用。 好的,好的!谢谢你解释这个! :) 那么我将不得不对我的代码进行一些更改。【参考方案3】:

尝试改变类型:

var val1 = datareader.GetValue(index);    
var convertedValue = (val1 == DBNull.Value) ? null : Convert.ChangeType(val1, info.PropertyType);                            
info.SetValue(myobj, convertedValue, null);

【讨论】:

它给出了另一个错误:System.InvalidCastException: 'Invalid cast from 'System.Int16' to 'System.Nullable`1[[System.Int32,...]] System.InvalidCastException: '从 'System.Int16' 到 'System.Nullable`1[[System.Int32, ]] 的无效转换

以上是关于“System.Int16”类型的对象无法转换为“System.Nullable”1[System.Int32] 类型的主要内容,如果未能解决你的问题,请参考以下文章

C#调用C++的DLL搜集整理的所有数据类型转换方式

无法将类型为“System.DateTime”的对象强制转换为类型“System.String”

无法将类型为“System.Collections.Generic.List`1[EPMS.Domain.SingleItem]”的对象强制转换为类型“EPMS

无法将 java.lang.String 类型的对象转换为类型 - FirebaseUI

无法将 java.lang.Boolean 类型的对象转换为类型

无法将 Person 类型的对象转换为 PersonViewModel 类型