我有一個實現IList接口的類。我需要這個列表的「排序視圖」,但不需要修改它(我不能直接對IList類進行排序)。SortList複製密鑰,但它不應該
當原始列表被修改時,這些視圖應該被更新,保持項目排序。所以,我介紹了一個SortList創建方法,該方法創建一個SortList,其中包含一個用於包含在原始列表中的特定對象的比較器。
這裏是代碼段:
public class MyList<T> : ICollection, IList<T>
{
public SortedList CreateSortView(string property)
{
try
{
Lock();
SortListView sortView;
if (mSortListViews.ContainsKey(property) == false)
{
// Create sorted view
sortView = new SortListView(property, Count);
mSortListViews.Add(property, sortView);
foreach (T item in Items)
sortView.Add(item);
} else
sortView = mSortListViews[property];
sortView.ReferenceCount++;
return (sortView);
}
finally
{
Unlock();
}
}
public void DeleteSortView(string property)
{
try
{
Lock();
// Unreference sorted view
mSortListViews[property].ReferenceCount--;
// Remove sorted view
if (mSortListViews[property].ReferenceCount == 0)
mSortListViews.Remove(property);
}
finally
{
Unlock();
}
}
protected class SortListView : SortedList
{
public SortListView(string property, int capacity)
: base(new GenericPropertyComparer(typeof(T).GetProperty(property, BindingFlags.Instance | BindingFlags.Public)), capacity)
{
}
public int ReferenceCount = 0;
public void Add(T item)
{
Add(item, item);
}
public void Remove(T item)
{
base.Remove(item);
}
class GenericPropertyComparer : IComparer
{
public GenericPropertyComparer(PropertyInfo property)
{
if (property == null)
throw new ArgumentException("property doesn't specify a valid property");
if (property.CanRead == false)
throw new ArgumentException("property specify a write-only property");
if (property.PropertyType.GetInterface("IComparable") == null)
throw new ArgumentException("property type doesn't IComparable");
mSortingProperty = property;
}
public int Compare(object x, object y)
{
IComparable propX = (IComparable)mSortingProperty.GetValue(x, null);
IComparable propY = (IComparable)mSortingProperty.GetValue(y, null);
return (propX.CompareTo(propY));
}
private PropertyInfo mSortingProperty = null;
}
private Dictionary<string, SortListView> mSortListViews = new Dictionary<string, SortListView>();
}
實際上,類用戶請求創建一個SortListView指定哪些確定的分選的屬性名稱,以及使用該反射每個SortListView定義的不斷排序的一個的IComparer項目。 無論何時添加或從原始列表中刪除項目,每個創建的SortListView都將使用相同的操作進行更新。
這似乎擅長的第一次機會,但它創造了我的問題,因爲它給我增加項目sortlist中的時以下異常:
System.ArgumentException:項目已添加。鍵入字典:'PowerShell_ISE [C:\ Windows \ sysWOW64 \ WindowsPowerShell \ v1.0 \ PowerShell_ISE.exe]'添加密鑰:'PowerShell_ISE [C:\ Windows \ system32 \ WindowsPowerShell \ v1.0 \ PowerShell_ISE.exe]'
你可以從異常消息,由SortedListView.Add(object)
拋出看,鑰匙(列表項的對象)的字符串表示是不同的(注意,可執行文件的路徑)。
爲什麼SortList會給我這個異常?
爲了解決這個問題我想實現一個GetHashCode()
爲基本對象,但沒有成功:
public override int GetHashCode()
{
return (
base.GetHashCode()^
mApplicationName.GetHashCode()^
mApplicationPath.GetHashCode()^
mCommandLine.GetHashCode()^
mWorkingDirectory.GetHashCode()
);
}
我忘了說,這與一些對象只發生值(約5%)。所以,當原始列表包含100個項目時,「排序視圖」僅包含95個項目。 – Luca 2011-01-09 11:09:43
當propX.CompareTo(propY)`返回0時,你可以通過設置一個斷點來試圖調試`GenericPropertyComparer`嗎?所以你將能夠理解比較器是否工作正確,如果值實際上等於... – digEmAll 2011-01-09 11:21:19
@digEmAll你明白了!我注意到IComparable.CompareTo不會調用GetHashCode!哎喲!我需要一些關於SortList IComparer函數的說明。現在我明白爲什麼每個人都試圖在SortList中重複鍵值:他們想要對鍵值進行排序,這些鍵值可以被複制(在我的情況下,「ApplicationName」視圖是重複的,但不是「ApplicationPath」)。 – Luca 2011-01-09 11:31:30