如何将这两个类似的方法重构为一个?

Tho*_*ock 5 c# generics refactoring

我已经看到一些使用'T'的样本来使一个方法可以重用于不同类的泛型集合,但我从来没有真正深入到它或理解样本.

我想知道是否有可能将下面的两种方法合二为一,这样做的缺点是(性能方面).

任何人?

        [NonAction]
        public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, string defaultOption)
        {
            var items = departments.Select(d => new SelectListItem() { Text = d.Code + " - " + d.Description, Value = d.Id.ToString() }).ToList();
            items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
            return items;
        }

        [NonAction]
        public List<SelectListItem> ToSelectList(IEnumerable<Function> functions, string defaultOption)
        {
            var items = functions.Select(f => new SelectListItem() { Text = f.Description, Value = f.Id.ToString() }).ToList();
            items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
            return items;
        }
Run Code Online (Sandbox Code Playgroud)

我使用的解决方案:

用法

var departmentItems = departments.ToSelectList(d => d.Code + " - " + d.Description, d => d.Id.ToString(), " - ");
var functionItems = customerFunctions.ToSelectList(f => f.Description, f => f.Id.ToString(), " - ");
Run Code Online (Sandbox Code Playgroud)

 public static class MCVExtentions
    {
        public static List<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption)
        {
            var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList();
            items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
            return items;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Grz*_*nio 8

旧学校的方式是为Department和Function创建一个通用界面:

interface A
{
int ID{get;}
string Description{get;}
}
Run Code Online (Sandbox Code Playgroud)

您在Department上实现Description以返回d.Code + " - " + d.Description.并编写函数来使用此接口而不是具体类:

[NonAction]
    public List<SelectListItem> ToSelectList(IEnumerable<A> as, string defaultOption)
    {
        var items = as.Select(a => new SelectListItem() { Text = a.Description, Value = a.Id.ToString() }).ToList();
        items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
        return items;
    }
Run Code Online (Sandbox Code Playgroud)

编辑:关于使用泛型,在这种情况下它不会有太多帮助,因为

  • 您传递的对象需要实现Id和Description
  • 你没有归还这些物品,所以在这方面你不必关心仿制药的类型安全性

  • 我会说在这种情况下使用泛型和函数会更好.然后,您不必强制一堆类来实现接口.您可能希望在没有ID或描述的类上使用该ToSelectList函数,并且添加它的位置不是很合理(或者例如,Description属性应该被称为其他内容). (2认同)

bru*_*nde 7

如果没有实现@Grzenio建议的通用接口,您可以使用如下通用方法:

    public List<SelectListItem> ToSelectList<T>(IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption)
    {
        var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList();
        items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
        return items;
    }

    // use like

    t.ToSelectList(departments, d => d.Code + " - " + d.Description, d => d.Id.ToString(), "default");
    t.ToSelectList(functions, f => f.Description, f => f.Id.ToString(), "default");
Run Code Online (Sandbox Code Playgroud)