方法返回泛型函数c#

时间:2014-01-21 12:54:12

标签: c# linq generics

是否可以从方法返回通用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; }
}

这可能吗?或者我走错了路?

3 个答案:

答案 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#编译器找不到intstring之间的现有转换以及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;
    }
}