简单的问题。我正在VS 2010 C#中编写应用程序以获得乐趣(学习体验),我不知道如何以可接受的方式解决问题。
假设我有一个名为“Biscuit”的课程
class Biscuit
{
private string Brand = String.Empty;
private string Variant = String.Empty;
public void CreateBiscuit(string pBrand, string pVariant)
{
Brand = pBrand;
Variant = pVariant;
}
public void GetDetails(ref string pBrand, ref string pVariant)
{
pBrand = Brand;
pVariant = Variant;
}
}
用户可以根据需要创建此对象的任意数量的实例。他们所要做的就是提供品牌和变体。然后我创建对象并将其存储在列表中
问题是,我不希望有重复。所以没有两个对象,其中Brand和Variant都与另一个实例相同。
我可以遍历BiscuitLibrary中的所有对象,但这似乎不是好的练习,也不是很好的表现。 (下面的当前代码)
List<Biscuit> BiscuitLibrary = new List<Biscuit>();
public void CheckDuplicate(string pBrand, string pVariant)
{
string ObjectBrand = String.Empty
string ObjectVariant = String.Empty;
foreach (Biscuit CurrentItem in BiscuitLibrary)
{
CurrentItem.GetDetails(ref ObjectBrand, ref ObjectVariant);
if ((ObjectBrand == pBrand) && (ObjectVariant == pVariant))
{
MessageBox.Show("This Biscuit Already Exists, Sorry!");
}
else
{
Biscuit NewBiscuit = new Biscuit();
NewBiscuit.CreateBiscuit(pBrand, pVariant);
BiscuitLibrary.Add(NewBiscuit);
}
}
}
我该怎么做?
谢谢,汤姆!
答案 0 :(得分:1)
最佳做法可能是将所有实例存储在HashSet而不是List中。如果您计划存储数千个实例,这对性能尤其有用。在列表中查看每个列表并检查重复项将是一项昂贵的操作。 HashSet以允许非常有效的重复检查的方式基于对象哈希码组织其内容。您可以在此处阅读有关HashSet的更多信息: http://msdn.microsoft.com/en-us/library/bb397727(v=vs.110).aspx
在使用HashSet之前,您必须通过重写其GetHashCode()和Equals()方法来准备您的类:
class Biscuit
{
public string Brand { get; set; }
public string Variant { get; set; }
public Biscuit(string brand, string variant)
{
Brand = brand;
Variant = variant;
}
public override bool Equals(object obj)
{
if (obj == null || typeof(Biscuit) != obj.GetType())
return false;
Biscuit biscuitObj = obj as Biscuit;
return biscuitObj.Brand == this.Brand && biscuitObj.Variant == this.Variant;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + this.Brand.GetHashCode();
hash = hash * 23 + this.Variant.GetHashCode();
return hash;
}
}
}
现在您可以将此类与HashSet一起使用:
//we create a HashSet and add 4 biscuits to it
//one of the biscuits is duplicate and will not be inserted
var uniqueBiscuitBox = new HashSet<Bisquit>();
uniqueBiscuitBox.Add(new Biscuit("A", "1"));
uniqueBiscuitBox.Add(new Biscuit("A", "1"));
uniqueBiscuitBox.Add(new Biscuit("B", "1"));
uniqueBiscuitBox.Add(new Biscuit("C", "4"));
Console.WriteLine(uniqueBiscuitBox.Count()); //returns 3
答案 1 :(得分:0)
由于您已经使用类似于Factory模式的东西,您可以对代码进行一些修改,使其按照您的意愿运行:
class Biscuit
{
// You should use properties
public string Brand {get; private set;}
public string Variant {get; private set;}
// Use a protected constructor so it can't be used outside the class
protected Biscuit(string brand, string variant)
{
Brand = brand;
Variant = variant;
}
// Use a static list to hold the already crated biscuits
private static List<Biscuit> _existingBiscuits = new List<Biscuit>();
// "Factory method" to create Biscuit instances
public static Biscuit CreateBiscuit(string pBrand, string pVariant)
{
// Use LINQ to find if there are any biscuits already crated with the brand and variant
if (_existingBiscuits.Any(b => b.Brand == pBrand && b.Variant == pVariant))
{
// If the biscuit already exist return null, no biscuit created
return null;
}
else
{
// Create biscuit and add it to the list
var biscuit = new Biscuit(pBrand, pVariant);
_existingBiscuits.Add(biscuit);
return biscuit;
}
}
}
答案 2 :(得分:0)
第一个建议:要求实例用有效数据构建;如果用户尝试传递无效数据并且避免“构造然后初始化”反模式,则抛出。
public class Biscuit : IEquatable<Biscuit>
{
public string Brand { get; private set; }
public string Variant { get; private set; }
public Biscuit(string brand, string variant)
{
if (brand == null) throw new ArgumentNullException("brand");
if (variant == null) throw new ArgumentNullException("variant");
Brand = brand;
Variant = variant;
}
public bool Equals(Biscuit b)
{
if (b == null) return false;
return string.Equals(Brand, b.Brand, StringComparison.InvariantCulture)
&& string.Equals(Variant, b.Variant, StringComparison.InvariantCulture);
}
}
如果您想要一个包含特殊规则的列表(例如,没有两个项目具有相同的Brand和Variant),则创建一个实现规则的类。不要使用通用列表并尝试在运行时强制执行规则。
复制@ SoftwareFactor的想法,您可以使用HashSet
创建强类型IEqualityComparer
:
class BiscuitEqualityComparer : IEqualityComparer<Biscuit>
{
public bool Equals(Biscuit b1, Biscuit b2)
{
if (b1 == null) return b2 == null;
return b1.Equals(b2);
}
public int GetHashCode(Biscuit b)
{
if (b == null) throw new ArgumentNullException("b");
return b.Brand.GetHashCode() ^ b.Variant.GetHashCode();
}
}
var bh = new HashSet<Biscuit>(new BiscuitEqualityComparer());
bh.Add(new Biscuit("Alpha", "Beta"));
bh.Add(new Biscuit("Alpha", "Gamma"));
bh.Add(new Biscuit("Alpha", "Beta")); // will not be added.