C# 如何使此方法更通用?
我有一个叫做LoadToDictionary的方法。它接受字典和文件路径。目前,它看起来像这样:C# 如何使此方法更通用?,c#,C#,我有一个叫做LoadToDictionary的方法。它接受字典和文件路径。目前,它看起来像这样: void LoadToDictionary(Dictionary dict,string filePath。然后在内部,它会有很多代码来将filePath中的文件内容提取到字典中。我想让它更通用,这样它就可以,比如说,使用一个带int的字典,并且能够更改方法中的解析代码。我是否应该标记此方法并稍后重写它?是还有其他方法吗?过早的通用性让过早的优化成为罪恶的根源。通用性是昂贵的而昂贵的代码应该有明显的
void LoadToDictionary(Dictionary dict,string filePath
。然后在内部,它会有很多代码来将filePath中的文件内容提取到字典中。我想让它更通用,这样它就可以,比如说,使用一个带int的字典,并且能够更改方法中的解析代码。我是否应该标记此方法并稍后重写它?是还有其他方法吗?过早的通用性让过早的优化成为罪恶的根源。通用性是昂贵的而昂贵的代码应该有明显的好处
因此,我将根据具体的场景,在您的方法中增加通用性。我可以想出许多方法使您的方法更通用:
字典
;拿字典
操作
,其操作可能是在字典中输入项目IEnumerable
并让调用者为您解析流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... }