我有很多自定义集合类。每个用于提供各种自定义类型的集合 - 一个自定义类型到一个自定义集合。自定义集合继承List<T>
[其中T在这种情况下是特定的自定义类型,而不是通用]并提供一些附加功能。
我之前已经取消了自定义集合,并在其他地方使用了自定义方法,但我发现我扩展了代码,我需要使用自己的方法来收集集合。
一切正常,一切都快乐。但它让我很恼火,因为我知道我做得不好。问题是每个类使用几乎相同的代码,只改变类型和参数,所以我觉得它可以实现为抽象类,或者通用,或者List的扩展,或者......但是我&#39 ;我真的不了解差异,或者如何去理解我需要的东西。
以下是我的几个系列中的两个,以便您明白这一点:
// JourneyPatterns
public class JourneyPatterns : List<JourneyPattern>
{
private Dictionary<string, JourneyPattern> jpHashes; // This is a hash table for quick lookup of a JP based on its values
/* Add a journey pattern to the JourneyPatterns collection. Three methods for adding:
1. "Insert Before" (=at) a particular point in the list. This is the method used by all three methods.
2. "Insert After" a particular point in the list. This is "before" shifted by 1 e.g. "after 6" is "before 7"
3. "Append" to the end of the list. This is "before" with a value equal to the list count, and is the same as inherited "Add", but with checks
*/
public JourneyPattern InsertBefore(JourneyPattern JP, int before)
{
// check for a pre-existing JP with the same parameters (ignore ID). Do this by constructing a "key" based on the values to check against
// and looking it up in the private hash dictionary
JourneyPattern existingJP;
if (jpHashes.TryGetValue(JP.hash, out existingJP)) { return existingJP; }
else
{
// construct a new ID for this JP
if (string.IsNullOrWhiteSpace(JP.id)) JP.id = "JP_" + (Count + 1).ToString();
// next check that the ID specified isn't already being used by a different JPS
if (Exists(a => a.id == JP.id)) JP.id = "JP_" + (Count + 1).ToString();
// now do the add/insert
if (before < 0) { Insert(0, JP); } else if (before >= Count) { Add(JP); } else { Insert(before, JP); }
// finally add to the hash table for fast compare / lookup
jpHashes.Add(JP.hash, JP);
return JP;
}
}
public JourneyPattern InsertAfter(JourneyPattern JP, int after) { return InsertBefore(JP, after + 1); }
public JourneyPattern Append(JourneyPattern JP) { return InsertBefore(JP, Count); }
}
// JourneyPatternSections
public class JourneyPatternSections : List<JourneyPatternSection>
{
private Dictionary<string, JourneyPatternSection> jpsHashes; // This is a hash table for quick lookup of a JPS based on its values
/* Add a journey pattern section to the journeyPatternSections collection. Three methods for adding:
1. "Insert Before" (=at) a particular point in the list. This is the method used by all three methods.
2. "Insert After" a particular point in the list. This is "before" shifted by 1 e.g. "after 6" is "before 7"
3. "Append" to the end of the list. This is "before" with a value equal to the list count, and is the same as inherited "Add", but with checks
*/
public JourneyPatternSection InsertBefore(JourneyPatternSection JPS, int before)
{
// check for a pre-existing JPS with the same parameters (ignore ID). Do this by constructing a "key" based on the values to check against
// and looking it up in the private hash dictionary
JourneyPatternSection existingJPS;
if (jpsHashes.TryGetValue(JPS.hash, out existingJPS)) { return existingJPS; }
else
{
// construct a new ID for this JPS
if (string.IsNullOrWhiteSpace(JPS.id)) JPS.id = "JPS_" + (Count + 1).ToString();
// next check that the ID specified isn't already being used by a different JPS
if (Exists(a => a.id == JPS.id)) JPS.id = "JPS_" + (Count + 1).ToString();
// now do the add/insert
if (before < 0) { Insert(0, JPS); } else if (before >= Count) { Add(JPS); } else { Insert(before, JPS); }
// finally add to the hash table for fast compare / lookup
jpsHashes.Add(JPS.hash, JPS);
return JPS;
}
}
public JourneyPatternSection InsertAfter(JourneyPatternSection JPS, int after) { return InsertBefore(JPS, after + 1); }
public JourneyPatternSection Append(JourneyPatternSection JPS) { return InsertBefore(JPS, Count); }
}
正如您所看到的,不同的是类型(JourneyPattern或JourneyPatternSection),以及我用于&#34; id&#34;的前缀。类型的属性(&#34; JP _&#34;或&#34; JPS _&#34;)。其他一切都很常见,因为确定&#34;唯一性的方法&#34; (属性&#34; hash&#34;)是自定义类型的一部分。
我的一些自定义集合需要更多参与和不同的这些方法的实现,这很好,但这是最常见的一个,到目前为止我实施了大约6次似乎a)毫无意义,并且b)更难维护。
您的想法和帮助表示赞赏!
答案 0 :(得分:1)
假设JourneyPattern
和JourneyPatternSection
都实现了一个共同的interface
:
public interface IJourney
{
string hash { get; set; }
string id { get; set; }
}
您可以为集合实现基类:
public abstract class SpecializedList<T> : List<T> where T : class, IJourney
{
private Dictionary<string, T> jpHashes; // This is a hash table for quick lookup of a JP based on its values
protected abstract string IdPrefix { get; }
/* Add a journey pattern to the JourneyPatterns collection. Three methods for adding:
1. "Insert Before" (=at) a particular point in the list. This is the method used by all three methods.
2. "Insert After" a particular point in the list. This is "before" shifted by 1 e.g. "after 6" is "before 7"
3. "Append" to the end of the list. This is "before" with a value equal to the list count, and is the same as inherited "Add", but with checks
*/
public T InsertBefore(T JP, int before)
{
// check for a pre-existing JP with the same parameters (ignore ID). Do this by constructing a "key" based on the values to check against
// and looking it up in the private hash dictionary
T existingJP;
if (jpHashes.TryGetValue(JP.hash, out existingJP)) { return existingJP; }
else
{
// construct a new ID for this JP
if (string.IsNullOrWhiteSpace(JP.id)) JP.id = "JP_" + (Count + 1).ToString();
// next check that the ID specified isn't already being used by a different JPS
if (Exists(a => a.id == JP.id)) JP.id = IdPrefix + (Count + 1).ToString();
// now do the add/insert
if (before < 0) { Insert(0, JP); } else if (before >= Count) { Add(JP); } else { Insert(before, JP); }
// finally add to the hash table for fast compare / lookup
jpHashes.Add(JP.hash, JP);
return JP;
}
}
public T InsertAfter(T JP, int after) { return InsertBefore(JP, after + 1); }
public T Append(T JP) { return InsertBefore(JP, Count); }
}
然后实现每个集合:
public class JourneyPatterns : SpecializedList<JourneyPattern>
{
protected override string IdPrefix => "JP_";
}
public class JourneyPatternSections : SpecializedList<JourneyPatternSection>
{
protected override string IdPrefix => "JPS_";
}