【问题标题】:Pass an object variable to method - Specified cast is not valid将对象变量传递给方法 - 指定的强制转换无效
【发布时间】:2016-10-13 22:35:51
【问题描述】:

我有一个对象列表(它们的类型提前未知)。下面的示例显示了硬编码值,但我的实际代码通过从 CSV 文件中读取来填充 args 列表。然后,我想将此 args 列表传递给要求某些参数的典型方法。所以我将元素转换为所需的类型,如图所示。我收到错误:

指定的演员表无效

在运行时调用方法时。我应该怎么做呢?

var args = new List<object>();
        args.Add(5495);
        args.Add("String1");
        args.Add(10133);
        args.Add("String2");

        result = request.GetCustomer((long) args[0], (string) args[1], (int) args[2], (string) args[3]);

【问题讨论】:

  • 该错误专门告诉您为什么不能执行转换,包括对象的实际类型是什么以及您尝试将其转换为什么。如果您希望它在运行时不会失败,则需要将对象转换为其 实际 类型。
  • 好吧,一个好的开始是围绕这个问题的 try catch 块和计数,以便您可以看到 csv 中的哪一行是罪魁祸首。
  • @Kell A try/catch 块只会掩盖问题。他已经可以看到错误,他只需要修复代码中的错误。
  • 你会想要安全地转换这些值,所以args[0] as long
  • @Servy 错误可能在从 csv 文件传递​​给代码的数据中。

标签: c# object types casting


【解决方案1】:

当您向List&lt;object&gt;() 添加值类型时,

args.Add(5495);

该项目将为Boxed。上一行导致5495int 被装箱。要拆箱,您需要将args[0] 显式转换为其类型 - (int)args[0]。因此,如果您的方法接受long 作为其第一个参数,请执行(long)(int)args[0]。您将 args[0] 拆箱,然后将值转换为 long

【讨论】:

  • 谢谢!!!这解决了问题,我实际上意识到我可以将该参数转换为 (int) 而不是 (long)。
【解决方案2】:

让我们稍微简化一下问题。

var args = new List<object>();
args.Add(5495);
var l = (long)args[0]; // throws an exception

args[0] 里面到底是什么?一个int(因为5495 是编译器的一个int,如果你希望它是一个long,输入5495L)。更准确地说,一个盒装 int,因为您必须将它存储在引用类型的存储位置。装箱的结构只能拆箱到同一个结构或这个结构的可为空。在我们的例子中

var i = (int)args[0];
var nullable = (Nullable<int>)args[0];
var nullable1 == (int?)args[0];

一切都会好起来的。

您可以在拆箱后将该值转换为与其兼容的任何内容。

您可以在msdn 上阅读有关装箱和拆箱的更多信息。如果您想有效地使用 C#,这是一个非常宝贵的理解。

您的问题的根本原因是您使用的是List&lt;object&gt;,这使得拳击不可避免。您真的需要这样做的情况很少见,您可能应该重新考虑您的架构以避免它。

【讨论】:

  • 感谢有关装箱/拆箱的推荐读物(尤其是性能方面)。我就是个菜鸟。是的,这种设计可能并不理想。我不得不为每个方法调用具有 20-30 个参数的不同方法,因此我厌倦了为每个方法定义 20-30 个变量 --> 对象列表。如果您对我的情况有更好的建议,我会全力以赴。谢谢!
  • 20-30 个参数很多。任何理智的方法可能都不应该有那么多。您可能应该重构一些对您的业务逻辑有意义的自定义类中的大部分对象,并将其中一些对象传递给您的方法。
  • 这些主要是创建某些类型数据的 Web 服务方法(例如,包含大量关于公司数据的公司记录)。是的,我可能会重构一些常见的字段。
【解决方案3】:

为商店列表数据创建单独的类

类测试{

private long Variable1{get;set;}

私有字符串变量2{get;set;}

private long Variable3{get;set;}

私有字符串变量4{get;set;}

}

var args=new List();

var obj=new 测试{

变量 1=5495,

Variable2="String1",

变量3=10133,

Variable4="String2"

}

args.add(obj);

result=request.GetCustomer(args[0].Variable1,args[0].Variable2,args[0].Variable3,args[0].Variable4);

【讨论】:

    【解决方案4】:

    尝试使用 Convert.ChangeType

          var args = new List<object>();
            args.Add(5495);
            args.Add("String1");
            args.Add(10133);
            args.Add("String2");
    
    
            long aLong = (long)Convert.ChangeType(args[0], typeof(long), CultureInfo.InvariantCulture);
    
            string aStr = (string)Convert.ChangeType(args[1], typeof(string), CultureInfo.InvariantCulture);
    
            int aInt = (int)Convert.ChangeType(args[2], typeof(int), CultureInfo.InvariantCulture);
    

    【讨论】:

      【解决方案5】:

      问题是 5495 将具有 int 类型,而您正试图将其转换为 long。您可以通过多种方式解决此问题,这里是其中之一;

      替换这个;

      (long) args[0]
      

      有了这个;

      (long) (int) args[0]
      

      这不是一个非常有用的解决方案,但是因为您实际上永远无法将长值传递给您的方法,而是您可以这样做;

      args.Add((long) 5495);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-27
        • 2014-07-30
        • 2012-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多