使用 LINQ 的 .Cast() 运算符时,显式/隐式转换运算符失败 [英] Explicit/implicit cast operator fails when using LINQ's .Cast() operator

查看:32
本文介绍了使用 LINQ 的 .Cast() 运算符时,显式/隐式转换运算符失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用具有显式(但也因隐式失败)的强制转换运算符的类,该运算符在使用 LINQ 的 Cast<T>() 函数时失败.这是两个类的定义

公共类 DatabaseInfoElement : ConfigurationElement{[ConfigurationProperty("AllowedServer", IsRequired = true)]公共字符串 AllowedServer { get { return (string)base["AllowedServer"];} }[ConfigurationProperty("DatabaseName", IsRequired = true)]public string DatabaseName { get { return (string)base["DatabaseName"];} }[ConfigurationProperty("SqlInstance", IsRequired = true)]public string SqlInstance { get { return (string)base["SqlInstance"];} }公共静态显式运算符 DatabaseInfo(DatabaseInfoElement 元素){return new DatabaseInfo(element.AllowedServer, element.DatabaseName, element.SqlInstance);}}公共类数据库信息{公共数据库信息(字符串 allowedServer,字符串 sqlInstance,字符串数据库名称){AllowedServer = allowedServer;SqlInstance = sqlInstance;数据库名称 = 数据库名称;}公共字符串 AllowedServer { get;放;}公共字符串 SqlInstance { 获取;放;}公共字符串数据库名称 { 获取;放;}}

这是我用来测试它的代码.

//获取包含集合Databases"的ConfigurationSectionvar section = DatabaseInfoConfig.GetSection();//这条线完美无缺.DatabaseInfo test = (DatabaseInfo)section.Databases[0];//这一行抛出一个执行var test2 = new List(section.Databases.Cast());

这是我得到的例外

<前>System.InvalidCastException 未被用户代码处理HResult=-2147467262Message=无法将Server.Config.DatabaseInfoElement"类型的对象转换为Server.DatabaseInfo"类型.来源=系统.核心堆栈跟踪:在 System.Linq.Enumerable.d__b1`1.MoveNext()在 System.Collections.Generic.List`1..ctor(IEnumerable`1 集合)在 Sandbox.Main() 在 E:CodeSandboxProgram.cs:line 82内部异常:

我在演员阵容中做错了什么才能让它按照我想要的方式工作?

解决方案

当您定义显式/隐式强制转换运算符时,它们会在编译时绑定在调用站点上.这就是第一行起作用的原因:编译器可以计算出所需的所有类型信息,因此它可以将您的自定义显式转换运算符替换为默认的.

然而,由于 Cast 只是执行通用转换,编译器不知道您的运算符,因此它被忽略.结果:无效的强制转换异常.

您可以通过执行 .Select(x => (DatabaseInfo)x) 来解决此问题.或者,您可以添加一个名为 ToDatabaseInfo() 的方法,这样您就不会隐藏实际发生的事情.

I am trying to use a class that has a explicit (but also fails with implicit) cast operator that fails when using LINQ's Cast<T>() function. Here is the definitions of the two classes

public class DatabaseInfoElement : ConfigurationElement
{
    [ConfigurationProperty("AllowedServer", IsRequired = true)]
    public string AllowedServer { get { return (string)base["AllowedServer"]; } }

    [ConfigurationProperty("DatabaseName", IsRequired = true)]
    public string DatabaseName { get { return (string)base["DatabaseName"]; } }

    [ConfigurationProperty("SqlInstance", IsRequired = true)]
    public string SqlInstance { get { return (string)base["SqlInstance"]; } }

    public static explicit operator DatabaseInfo(DatabaseInfoElement element)
    {
        return new DatabaseInfo(element.AllowedServer, element.DatabaseName, element.SqlInstance);
    }

}

public class DatabaseInfo
{
    public DatabaseInfo(string allowedServer, string sqlInstance, string databaseName)
    {
        AllowedServer = allowedServer;
        SqlInstance = sqlInstance;
        DatabaseName = databaseName;
    }

    public string AllowedServer { get; set; }
    public string SqlInstance { get; set; }
    public string DatabaseName { get; set; }
}

Here is the code I am using to test it.

//Gets the ConfigurationSection that contains the collection "Databases"
var section = DatabaseInfoConfig.GetSection();

//This line works perfectly.
DatabaseInfo test = (DatabaseInfo)section.Databases[0];

//This line throws a execption
var test2 = new List<DatabaseInfo>(section.Databases.Cast<DatabaseInfo>());

Here is the exception I get

System.InvalidCastException was unhandled by user code
  HResult=-2147467262
  Message=Unable to cast object of type 'Server.Config.DatabaseInfoElement' to type 'Server.DatabaseInfo'.
  Source=System.Core
  StackTrace:
       at System.Linq.Enumerable.d__b1`1.MoveNext()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at Sandbox.Main() in E:CodeSandboxProgram.cs:line 82
  InnerException: 

What am I doing wrong in my casting to get this to work the way I want?

解决方案

When you define explicit/implicit cast operators, they are bound at call-sites at compile-time. That's why the first line works: the compiler can work out all the type information needed, and so it can substitute your custom explicit cast operator for the default one.

However, since the Cast<T> just performs a generic cast, the compiler doesn't know about your operator, and thus it is ignored. Result: invalid cast exception.

You can get around this by instead performing a .Select(x => (DatabaseInfo)x). Alternatively, you could add on a method called ToDatabaseInfo(), so that you're not hiding what's actually going on.

这篇关于使用 LINQ 的 .Cast() 运算符时,显式/隐式转换运算符失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆