Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩展方法失败,但(type)对象正常工作_C#_Linq_Casting_Extension Methods - Fatal编程技术网

C# 扩展方法失败,但(type)对象正常工作

C# 扩展方法失败,但(type)对象正常工作,c#,linq,casting,extension-methods,C#,Linq,Casting,Extension Methods,为了在一些LINQ到SQL对象和DTO之间转换,我们在DTO上创建了显式强制转换操作符。这样我们可以做到以下几点: DTOType MyDTO = (LinqToSQLType)MyLinq2SQLObj; 这很有效 但是,当您尝试使用LINQ.cast扩展方法强制转换时,它会抛出一个无效的强制转换异常,表示无法将类型Linq2SQLType强制转换为类型DTOType。i、 e.以下选项不起作用 List<DTO.Name> Names = dbContact.tNames.Ca

为了在一些LINQ到SQL对象和DTO之间转换,我们在DTO上创建了显式强制转换操作符。这样我们可以做到以下几点:

DTOType MyDTO = (LinqToSQLType)MyLinq2SQLObj;
这很有效

但是,当您尝试使用LINQ.cast扩展方法强制转换时,它会抛出一个无效的强制转换异常,表示无法将类型Linq2SQLType强制转换为类型DTOType。i、 e.以下选项不起作用

List<DTO.Name> Names = dbContact.tNames.Cast<DTO.Name>()
                                               .ToList();
下面的方法也很好用

List<DTO.Name> Names = dbContact.tNames.Select(name => (DTO.Name)name)
                                               .ToList();
为什么.Cast扩展方法抛出无效的强制转换异常?在过去,我曾多次以这种方式使用.Cast扩展方法,当您将诸如基类型之类的内容强制转换为派生类型时,它可以正常工作,但当对象具有显式强制转换运算符时,它就会失效

强制转换扩展方法不应用用户定义的转换。它只能强制转换到接口或所提供类型的类继承者权限内

用户定义的转换在编译时根据表达式中涉及的静态类型进行标识。它们不能作为运行时转换应用,因此以下内容是非法的:

public class SomeType
{
  public static implicit operator OtherType(SomeType s) 
  { 
    return new OtherType(); 
  }
}

public class OtherType { }

object x = new SomeType();
OtherType y = (OtherType)x; // will fail at runtime
UDC是否从某个类型存在到另一个类型并不重要——它不能通过object类型的引用应用。尝试运行上述代码将在运行时失败,报告如下:

System.InvalidCastException: 
    Unable to cast object of type 'SomeType' to type 'OtherType'
强制转换只能执行保留表示的转换。。。这就是为什么不能使用它来应用用户定义的转换


Eric Lippert有一篇关于Linq程序集的伟大文章,这篇文章总是值得一读。

如果您对Linq程序集进行反编译,您会得到类似以下的代码。前面的答案是正确的,最终转换是从“对象”到目标类型,这对于自定义类型来说总是失败的

private static IEnumerable<TResult> CastIterator<TResult>( IEnumerable source )
{
    foreach(object current in source)
    {
        yield return (TResult)( (object)current );
    }
    yield break;
}

public static IEnumerable<TResult> DCast<TResult>( this IEnumerable source )
{
    IEnumerable<TResult> enumerable = source as IEnumerable<TResult>;
    if(enumerable != null)
    {
        return enumerable;
    }
    if(source == null)
    {
        throw new ArgumentNullException( "source" );
    }
    return CastIterator<TResult>( source );
}

TFish

对于那些遇到此问题并正在寻找解决方法的人

Dim res = arrayOfStrings.Select(Function(__) CType( __, YourType ))

不确定C的确切语义,但我相信这很容易。

我的问题是,我已经观察到了您通过经验描述的行为,我想问的是,为什么它不适用于用户定义的转换。与显式cast操作符不起作用的有什么不同之处,它是如何进行转换的?Ben:在你写评论时,我正在详细阐述我的答案:让我知道这是否为cast的工作方式提供了清晰的解释。好的,是的,这是有意义的,谢谢,我对reflector做了一点挖掘,它几乎无法辨认,但它确实暗示了你的解释,谢谢。@Ben:想象一下你正在构建一个类似CLR的运行时。您真的想在运行时嵌入C编程语言的绑定转换规则吗?如果VB/F/JScript/Perl/Ruby/C/C++/J/Python/。。。规则不同?为什么要在运行时对C规则进行特殊处理?因此,您在运行时获得的规则是最简单的最低公分母;只是一个型式试验。如果您想要编译时行为,可以使用C 4中的dynamic在运行时获取它,或者编写代码以便在编译时完成转换的解析。可能重复感谢您的输入,但我理解了原始答案。
Dim res = arrayOfStrings.Select(Function(__) CType( __, YourType ))