【发布时间】:2016-06-15 21:49:17
【问题描述】:
我有两种类型都扩展了一个通用的基本类型。这两种类型都没有额外的属性,只为抽象值赋值。当我尝试使用CompareTo 比较这两种类型时,我得到一个异常堆栈跟踪一英里长,它源于一个失败的类型案例。
如果我尝试使用泛型进行强制转换,是否可以比较这两种类型?
代码如下:
起始类型:
public interface IIdentifier : IEquatable<IIdentifier>, IComparable<IIdentifier>
{
/// <summary>
/// Numerical identifier
/// </summary>
long Id { get; }
/// <summary>
/// Provide the type of identifier.
/// </summary>
IdentifierType IdType { get; }
}
接下来两种类型扩展的基本标识符类型:
[DataContract]
public abstract class BaseIdentifier<T> : IIdentifier, IComparable<BaseIdentifier<T>>, IComparable, IEquatable<BaseIdentifier<T>> where T : class, IIdentifier
{
#region Properties
[DataMember(Order = 1)]
public long Id { get; set; }
[IgnoreDataMember]
public abstract IdentifierType IdType { get; }
#endregion
#region Constructors
protected BaseIdentifier(long id)
{
Id = id;
}
protected BaseIdentifier()
{
}
#endregion
#region IEquatable<IIdentifier> Members
public bool Equals(IIdentifier other)
{
if (ReferenceEquals(other, null))
return false;
return this.IdType == other.IdType && this.Id == other.Id;
}
#endregion
#region IComparable<IIdentifier> Members
public int CompareTo(IIdentifier other)
{
int c = this.IdType.CompareTo(other.IdType);
if (c != 0)
c = this.Id.CompareTo(other.Id);
return c;
}
#endregion
#region IComparable<BaseIdentifier<T>> Members
public int CompareTo(BaseIdentifier<T> other)
{
return Id.CompareTo(other.Id);
}
#endregion
#region IComparable
public int CompareTo(object obj)
{
return CompareTo(obj as BaseIdentifier<T>);
}
#endregion
#region IEquatable<BaseIdentifier<T>> Members
public bool Equals(BaseIdentifier<T> other)
{
if (ReferenceEquals(other, null))
return false;
return this.Id == other.Id;
}
#endregion
}
以下是使用BaseIdentifier<T> 函数尝试CompareTo 时抛出异常的两种类型。
[DataContract]
public class Type1 : BaseIdentifier<Type1>
{
[IgnoreDataMember]
public override IdentifierType IdType
{
get { return IdentifierType.Type1; }
}
public Type1(long Id)
: base(Id)
{
}
public Type1()
{
// For serialization
}
}
[DataContract]
public class Type2 : BaseIdentifier<Type2>
{
[IgnoreDataMember]
public override IdentifierType IdType
{
get { return IdentifierType.Type2; }
}
public Type1(long Id)
: base(Id)
{
}
public Type2()
{
// For serialization
}
}
例外:
"Unable to cast object of type 'Domain.Contracts.Type2'
to type 'Domain.Contracts.Type1`1[Domain.Contracts.Type1]'.""
at Domain.Contracts.BaseIdentifier`1.CompareTo(Object obj) in
C:\\xsr\\path\\BaseIdentifier.cs:line 109\r\n
at Xceed.Utils.Data.ObjectDataStore.CompareData(Object xData, Object yData)\r\n
at Xceed.Utils.Data.ObjectDataStore.Compare(Int32 xRecordIndex, Int32 yRecordIndex)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionViewSort.Compare(Int32 xDataIndex, Int32 yDataIndex)\r\n
at Xceed.Utils.Collections.IndexWeakHeapSort.Sort(Int32 length)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionViewGroupRoot.SortRootRawItems(SortDescriptionInfo[] sortDescriptionInfos, List`1 globalRawItems)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionView.SortItems(SortDescriptionInfo[] sortDescriptionInfos)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionView.ExecuteSourceItemOperation(DeferredOperation deferredOperation, Boolean& refreshForced)\r\n
at Xceed.Wpf.DataGrid.DeferredOperationManager.Process(Boolean processAll)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.DeferRefreshHelper.ProcessDispose(DataGridCollectionViewBase collectionView)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.DeferRefreshHelper.Dispose(Boolean disposing)\r\n
at Xceed.Wpf.DataGrid.DataGridCollectionViewBase.DeferRefreshHelper.System.IDisposable.Dispose()\r\n
at Xceed.Wpf.DataGrid.DataGridSortDescriptionCollection.DeferResortDisposable.Dispose()\r\n
at Xceed.Wpf.DataGrid.ColumnSortCommand.Disposer.Dispose(Boolean disposing)"
【问题讨论】:
-
什么是exact异常?如果堆栈跟踪是“一英里长”,听起来您可能有无限递归。你能在调试器中运行它并在
CompareTo方法中中断吗? -
这是一英里长,因为它试图在第三方网格系统的比较中从空类型中获取属性。所以第三方网格系统是导致异常如此长的原因。查看异常的更新
标签: c# generics comparison