我正在编写一个带有以下签名的方法:
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>
。
由于我依赖该类型执行其他复杂操作,因此以下所有操作均失败。 我虽然它与重新编译解决方案有关,所以我清理并重新编译,但这一点不起作用。
老实说,我仍然有一个工作的解决方法,但关键是要了解我是否面临某种编译错误或其他什么。
有什么想法吗?你可以重现吗?
答案 0 :(得分:3)
因此,让我们看看编译器在传递Expression<Func<TSourceProperty, TDestinationProperty>> converter
的lambda时可以推断出表达式c => c == null ? 0 : c
的内容。我们知道c
是第一个参数解析后的Nullable<int>
,因此TSourceProperty
为Nullable<int>
,您似乎没有任何问题。那么这个表达的价值是什么?表达式调用条件运算符;第一个操作数的类型为int
,第二个操作的类型为Nullable<int>
,因为c
是int
。那么整个条件运算符的类型应该是什么?好吧,由于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)
问题在于?:
运算符,它会返回一个与0
和c
兼容的类型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)
它应该可以正常工作。