How to refactor these 2 similar methods into one?

前端 未结 3 1516
执念已碎
执念已碎 2021-02-10 00:36

I\'ve seen some samples of using \'T\' to make a method reuseable for generic collections of different classes, but I\'ve never really gotten into it or understood the samples.

相关标签:
3条回答
  • 2021-02-10 00:55

    Without implementiong a common interface like @Grzenio suggested, you could use a generic method like this:

        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");
    
    0 讨论(0)
  • 2021-02-10 01:11

    The old school way would be to create a common interface for both Department and Function:

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

    You implement Description on Department to return d.Code + " - " + d.Description. and write the function to use this interface instead of concrete classes:

    [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;
        }
    

    EDIT: Regarding using generics, its not going to help much in this case, because

    • the objects you are passing needs to implement Id and Description
    • you are not returning these objects, so in this respect you don't have to care about type safety of generics
    0 讨论(0)
  • 2021-02-10 01:19

    In fact you can do it with a combination of generics and functions, something along the lines of this (untested may not even compile).

    [NonAction]
    public List<SelectListItem> ToSelectList<T>(IEnumerable<T> en, 
                                                Function<string, T> text, 
                                                Function<string, T> 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;
    }
    

    Then you can dispatch to it with the appropriate lambda functions (or call directly).

    [NonAction]
    public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, 
                                             string defaultOption)
    {
        return ToSelectList<Department>(departments, d =>  d.Code + '-' + d.Description, d => d.Id.ToString(), defaultOption);
    
    }
    
    0 讨论(0)
提交回复
热议问题