生成泛型方法时可能出现编译错误

时间:2016-11-15 16:53:00

标签: c# generics

我正在编写一个带有以下签名的方法:

public class Map<TSource,TDestination>
{
    public void Map<TSourceProperty, TDestinationProperty>(
            Expression<Func<TSource, TSourceProperty>> sourcePropertySelector,
            Expression<Func<TDestination, TDestinationProperty>> destinationPropertySelector,
            Expression<Func<TSourceProperty, TDestinationProperty>> converter ){}

}

该方法被调用如下:

example1- Map( a => a.StringProperty, b => b.IntProperty, c => Int32.Parse( c ) )
example2- Map( a => a.NullabelInt32, b => b.Int32, c => c == null ? 0 : c)

当调用该方法时,发生TDestinationProperty并不总是正确的类型,即所选属性的确切类型。

在上面的示例中,TDestinationProperty的类型Int32正确;但是在示例2中,TDestinationProperty始终与TSourceProperty相同,即在示例2的特定情况下Nullable<int>

由于我依赖该类型执行其他复杂操作,因此以下所有操作均失败。 我虽然它与重新编译解决方案有关,所以我清理并重新编译,但这一点不起作用。

老实说,我仍然有一个工作的解决方法,但关键是要了解我是否面临某种编译错误或其他什么。

有什么想法吗?你可以重现吗?

2 个答案:

答案 0 :(得分:3)

因此,让我们看看编译器在传递Expression<Func<TSourceProperty, TDestinationProperty>> converter的lambda时可以推断出表达式c => c == null ? 0 : c的内容。我们知道c是第一个参数解析后的Nullable<int>,因此TSourcePropertyNullable<int>,您似乎没有任何问题。那么这个表达的价值是什么?表达式调用条件运算符;第一个操作数的类型为int,第二个操作的类型为Nullable<int>,因为cint。那么整个条件运算符的类型应该是什么?好吧,由于Nullable<int>可以隐式转换为Nullable<int>int 可以隐式转换为Nullable<int>,因此整个条件运算符的类型为{ {1}},这使得lambda的返回值的类型成为TDestinationProperty的类型。

如果您希望TDestinationProperty成为int,那么您需要将c转换为该lambda中的int。您可以写:c => c == null ? 0 : c.Value,但整个事情可以缩短为c => c.GetValueOrDefault()

答案 1 :(得分:2)

问题在于?:运算符,它会返回一个与0c兼容的类型Nullable<int>,因为c是一个Nullable<int>。而且,如果Func<TDestination, TDestinationProperty> TDestinationProperty Nullable<int> b.Int32由于自动提升类型而仍然是合法的返回类型,则使用第3个参数来确定类型。

如果您将第二行更改为

Map( a => a.NullabelInt32, b => b.Int32, c => c == null ? 0 : c.Value)

它应该可以正常工作。