是否可以从方法返回通用Func? 我想做的是像下面的GetSortFunc。
public class Example
{
private List<MyObject> _objects;
public Example()
{
_objects = new List<MyObject>
{
new MyObject {Id = 1, Name = "First", Value = 100.0},
new MyObject {Id = 2, Name = "Second", Value = 49.99},
new MyObject {Id = 3, Name = "Third", Value = 149.99}
};
}
public void Sort(SomeEnum sortOptions)
{
_objects = _objects.OrderBy(GetSortFunc(sortOptions));
}
private Func<MyObject, TKey> GetSortFunc(SomeEnum sortOptions)
{
switch (sortOptions)
{
case SomeEnum.First:
return x => x.Id;
case SomeEnum.Second:
return x => x.Name;
case SomeEnum.Third:
return x => x.Value;
}
}
}
SomeEnum和MyObject看起来像这样:
public enum SomeEnum
{
First,
Second,
Third
}
public class MyObject
{
public int Id { get; set; }
public string Name { get; set; }
public double Value { get; set; }
}
这可能吗?或者我走错了路?
答案 0 :(得分:3)
问题是返回类型会因TKey
的类型而异。此外,OrderBy
的类型参数也会有所不同。我建议您只复制OrderBy
来电:
IEnumerable<MyObject> ApplySortOrder(IEnumerable<MyObject> items, SomeEnum sortOptions)
{
switch (sortOptions)
{
case SomeEnum.First:
return items.OrderBy(x => x.Id);
case SomeEnum.Second:
return items.OrderBy(x => x.Name);
case SomeEnum.Third:
return items.OrderBy(x => x.Value);
}
}
或者,让GetSortFunc
返回delegate
并动态调用OrderBy
:
private Delegate GetSortFunc(SomeEnum sortOptions)
{
switch (sortOptions)
{
case SomeEnum.First:
return new Func<MyObject, int>(x => x.Id);
case SomeEnum.Second:
return new Func<MyObject, string>(x => x.Name);
case SomeEnum.Third:
return new Func<MyObject, int>(x => x.Value);
}
}
//...
Enumerable.OrderBy(_objects, (dynamic)GetSortFunc(sortOptions));
这会在运行时选择正确的重载。
答案 1 :(得分:2)
通用Func
或任何其他泛型类型只能从具有声明的泛型参数的上下文返回。此泛型参数需要存在于方法或方法的一个包含类型上。在这种情况下,没有通用参数,因此代码无法运行
这实际上不是一个应该是通用的函数的一个很好的例子。如果它是通用的,则需要看起来像这样
private Func<MyObject, TKey> GetSortFunc<TKey>(SomeEnum sortOptions)
{
switch (sortOptions)
{
case SomeEnum.First:
return x => (TKey)(object)x.Id;
case SomeEnum.Second:
return x => (TKey)(object)x.Name;
case SomeEnum.Third:
return x => (TKey)(object)x.Value;
}
}
所有丑陋的强制转换都存在,因为C#编译器找不到int
和string
之间的现有转换以及TKey
参数(因为它可以是字面上的任何类型)。除非属性的类型与TKey
匹配,否则它将无法工作,{{1}}通常是代码不能通用的标志。
答案 2 :(得分:2)
最简单的方法修复你的功能改变它
private Func<MyObject, object> GetSortFunc(SomeEnum sortOptions)
{
switch (sortOptions)
{
case SomeEnum.First:
return x => x.Id;
case SomeEnum.Second:
return x => x.Name;
case SomeEnum.Third:
return x => x.Value;
default:
return x => x.Id;
}
}