Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使此方法更通用?_C# - Fatal编程技术网

C# 如何使此方法更通用?

C# 如何使此方法更通用?,c#,C#,我有一个叫做LoadToDictionary的方法。它接受字典和文件路径。目前,它看起来像这样: void LoadToDictionary(Dictionary dict,string filePath。然后在内部,它会有很多代码来将filePath中的文件内容提取到字典中。我想让它更通用,这样它就可以,比如说,使用一个带int的字典,并且能够更改方法中的解析代码。我是否应该标记此方法并稍后重写它?是还有其他方法吗?过早的通用性让过早的优化成为罪恶的根源。通用性是昂贵的而昂贵的代码应该有明显的

我有一个叫做LoadToDictionary的方法。它接受字典和文件路径。目前,它看起来像这样:
void LoadToDictionary(Dictionary dict,string filePath
。然后在内部,它会有很多代码来将filePath中的文件内容提取到字典中。我想让它更通用,这样它就可以,比如说,使用一个带int的字典,并且能够更改方法中的解析代码。我是否应该标记此方法并稍后重写它?是还有其他方法吗?

过早的通用性让过早的优化成为罪恶的根源。通用性是昂贵的而昂贵的代码应该有明显的好处

因此,我将根据具体的场景,在您的方法中增加通用性。我可以想出许多方法使您的方法更通用:

  • 不要把字典中的字符串转换成字符串;把字典中的字符串转换成任意类型

  • 不要拿
    字典
    ;拿
    字典

  • 不要使用任何类型的字典。使用
    操作
    ,其操作可能是在字典中输入项目

  • 不要使用文件名。你只需要将文件名转换为流,所以首先使用流。让调用者为你打开流

  • 不要接受流。不管怎样,您只需要将流转换为一个项目序列,因此请使用
    IEnumerable
    并让调用者为您解析流

  • 我们能把它做得多一般?假设我们有一个T序列,然后它被转换成一个从K到V的映射。我们需要什么?一个序列、一个键提取器、一个值提取器和一个映射编写器:

    static void MakeMap<T, K, V>(this IEnumerable<T> sequence, Action<K, V> mapWriter, Func<T, K> keyExtractor, Func<T, V> valueExtractor)
    {
        foreach(var item in sequence)
            mapWriter(keyExtractor(item), valueExtractor(item));
    }
    
    静态void MakeMap(此IEnumerable序列、动作映射编写器、Func键提取器、Func值提取器)
    {
    foreach(序列中的var项目)
    mapWriter(键提取器(项)、值提取器(项));
    }
    
    请注意,当代码变得非常通用时,它是如何变得非常简短的。这是非常反常的通用,因此,调用站点现在看起来就像一团不洁的混乱。这真的是你想要的吗?你打算有效地使用所有这些通用性吗?可能不会。你实际有哪些场景驱动了欲望e更一般?使用那些特定的场景来激发您的重构

    这就是我们能做的吗?我们能不能比这更一般?当然。我们可以注意到,例如,它似乎有副作用。该方法不应该只是返回一个新构造的字典吗?该字典的比较策略应该是什么?如果有多个项具有相同的键呢?Sho它是否应该被替换,或者我们是否应该让字典实际上是从键到值列表的映射?我们可以采纳这些想法,并提出一种解决所有这些问题的新方法:

    public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, TElement> elementSelector,
    IEqualityComparer<TKey> comparer) { ... }
    
    公共静态ILookup ToLookup(
    这是一个数不清的来源,
    Func键选择器,
    Func元素选择器,
    IEqualityComparer比较器){…}
    

    嘿,我们刚刚重新发明了扩展方法。有时当你把一个方法变得足够通用时,你会发现它已经存在了。

    我在这里看到两个实际问题:
    1) 方法签名是否可以是动态的,以便它所期望的类型可以更改?
    2) 方法体是否可以是动态的,这样我的逻辑就可以动态地改变

    我不确定如果不使用反射和大量代码gen,这两种方法中的任何一种都可以实现。不过,我相信这里也有这样的人

    不过,根据您的需要,基本方法重载听起来就像您实际需要的

    以您的例子:

    void LoadToDictionary(Dictionary<string, string> dict, string filePath)
    { ... code here ... }
    
    //to have a LoadToDictionary method which accepts Dictionary<int, int>
    void LoadToDictionary(Dictionary<int, int> dict, string filePath)
    
    //To change the processing logic, you either need a new method name, 
    // or to override the original in an inheriting class
    
    void AlternateLoadToDictionary(Dictionary<string, string> dict, string filePath)
    override void LoadToDictionary(Dictionary<string, string> dict, string filePath)
    

    基本方法重载为您提供了很多灵活性。更重要的是,它允许您遵循雅格尼原则,而无需切断扩张渠道。如果需要,您可以随时回到代码中添加
    LoadToDictionary
    方法。

    我不得不说您是对的。你在这里提出了一些非常好的想法。我可能会重新思考其中的一些问题。+1从我这里得到了一个很棒的答案。我唯一的补充(纯粹的观点)是,如果你有一段代码,你可以使它更通用和可重用,你可以通过几个“传递”方法来简化你的代码,这些方法调用它,提供细节,例如,它在一个
    IDictionary
    上运行,这样您的调用代码就不会像Eric提到的那样变得异常复杂。这个答案真是太棒了。我完全同意。这就是雅格尼原则的作用。埃里克,有时候你写的答案在洞察力和内容上都非常出色,以至于我希望我有多个so账户,这样我就可以不止一次地投票了-请添加代码,以便我们更好地了解哪些方面可以改进。。。
    void LoadToDictionary(Dictionary<string, string> dict, string filePath)
    {
        string[] fileLines;
    
        if([yourBaseLineCondition])
        fileLines = LoadDataFromFile(filePath, false);
    
        else fileLines = LoadDataFromFile(filePath, true); 
    }
    
    string[] LoadDataFromFile(string filePath, bool altLogic)
    {
        if(altLogic) return LoadDataFromFileAlt(filePath)
        else
        { ... your logic ... }
    }
    
    string[] LoadDataFromFileAlt(string filePath)
    { ... your alt logic... }