我有两种类型都扩展了通用基类型。两种类型都没有其他属性,只为赋值赋值。当我尝试比较这两种类型时,使用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
}
以下是使用CompareTo
函数尝试BaseIdentifier<T>
时抛出exxeption的两种类型。
[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)"
答案 0 :(得分:0)
这与泛型在C#中的工作方式有关。通用语法实际上只是为了让您的生活更轻松,但您必须记住,更改泛型类型确实使其成为不同类型。因此,BaseIdentifier<Type1>
与BaseIdentifier<Type2>
完全不同。你在代码中写了一次,但在编译时它们是分开的。
弄清楚如何准确实现你的目标可能很复杂。基于上述示例的最简单选项是使其实现IComparible<IIdentifier>
而不是使用泛型类型。
答案 1 :(得分:0)
您的CompareTo(ojbect)
代码正在尝试将BaseIdentifier<Type1>
投放到不合法的BaseIdentifier<Type1>
。
由于您无法比较具有不同通用参数的对象,因此您似乎应该更改
public int CompareTo(object obj)
{
return CompareTo(obj as BaseIdentifier<T>);
}
到
public int CompareTo(object obj)
{
return CompareTo(obj as IIdentifier);
}
以便绑定到带有接口的重载,而不是泛型类型。
您可能还会考虑重载Equals(object)
,将其重定向到Equals(IIdentifier)
,这意味着 还需要重载GetHashCode
。