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

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

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

任何人?

[NonAction] public List ToSelectList(IEnumerable 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 ToSelectList(IEnumerable 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; } 

我使用的解决方案:

用法

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

  public static class MCVExtentions { public static List ToSelectList(this IEnumerable enumerable, Func text, Func 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; } } 

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

  public List ToSelectList(IEnumerable enumerable, Func text, Func 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"); 

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

 interface A { int ID{get;} string Description{get;} } 

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

 [NonAction] public List ToSelectList(IEnumerable 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; } 

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

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

实际上,您可以使用generics和函数的组合来实现它,这与此类似(未经测试甚至可能无法编译)。

 [NonAction] public List ToSelectList(IEnumerable en, Function text, Function value, string defaultOption) { var items = en.Select(x => new SelectListItem() { Text = text(x) , Value = value(x) }).ToList(); items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); return items; } 

然后你可以使用适当的lambda函数(或直接调用)调度它。

 [NonAction] public List ToSelectList(IEnumerable departments, string defaultOption) { return ToSelectList(departments, d => d.Code + '-' + d.Description, d => d.Id.ToString(), defaultOption); }