我遇到了一個場景,我需要根據輸入對不同屬性上的自定義類型列表進行排序。在幾篇文章的幫助下,我能夠使用LINQ提出泛型實現。在單元測試中,其中一個測試失敗,因爲使用表達式樹創建lamda表達式時發生隱式轉換。表達式樹中沒有發生隱式轉換
下面我把示例代碼來了解這個問題(不知道爲什麼格式沒有得到正確的,遺憾的是)
static class ExtensionMethods
{
public static IEnumerable<TSource> Sort<TSource>(this IEnumerable<TSource> unSortedList, Func<TSource, object> selector, bool isAscending)
{
return isAscending ? unSortedList.OrderBy(selector) : unSortedList.OrderByDescending(selector);
}
}
class Program
{
class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
static void Main(string[] args)
{
var unOrderedStudents = new List<Student>
{
new Student{ Name="A", Age=20},
new Student{Name = "B", Age=19}
};
//This Works
var sortUsingLamda = unOrderedStudents.Sort<Student>(stud => stud.Age, true);
//Exception - Expression of type 'System.Int32' cannot be used for return type 'System.Object'
var sortUsingExpressionTree = unOrderedStudents.Sort<Student>(GetSortFunc<Student>("Age"), true);
Console.WriteLine("Press any key to continue");
Console.ReadLine();
}
private static Func<T, object> GetSortFunc<T>(string sortColumn)
{
var param = Expression.Parameter(typeof(T), "entity");
var propertyExpression = Expression.Property(param, sortColumn);
var boxingExpression = Expression.Convert(propertyExpression, typeof(object));
return Expression.Lambda<Func<T, object>>(propertyExpression, param).Compile();
//after adding Convert expression issue got fixed
//return Expression.Lambda<Func<T, object>>(boxingExpression, param).Compile();
}
}
在Main方法,當我嘗試直接傳遞函數求代表排序擴展方法它的工作原理,但它與表達式樹失敗。
我發現了一個similar問題,但討論了約束類型參數。這兩個問題是否一樣?有人能幫我理解這個問題嗎?
這很有道理。如果我沒有錯,隱式轉換是在編譯時完成的,運行時完全沒有意識到這一點。由於表達式樹在運行時執行,因此需要有一個轉換節點來轉換它。如果我沒有正確理解,請糾正我。 – Moorthy 2011-05-31 16:12:25
@Moorthy - 是的,拳擊是編譯器中的explit(有一個操作碼)。然而,保持* reference-preserving *強制轉換爲基本類型是合法的,並且是無操作的(完全沒有任何操作) - 您可能會發現它的工作正常。 – 2011-05-31 16:42:26