C# IList<;T>;Count属性调用GetHashCode()(使用NHibernate)

C# IList<;T>;Count属性调用GetHashCode()(使用NHibernate),c#,nhibernate,ilist,C#,Nhibernate,Ilist,我遇到了一个奇怪的问题。 正如下面显示的代码,列表包含很多项。 代码list.Count==0有时会调用列表中项目的GetHashCode函数 public static bool IsNullOrEmpty<T>(this IList<T> list) { if (list == null) return true; return list.Count == 0; } class Item { int id; int

我遇到了一个奇怪的问题。 正如下面显示的代码,列表包含很多项。 代码
list.Count==0
有时会调用列表中项目的
GetHashCode
函数

public static bool IsNullOrEmpty<T>(this IList<T> list)
{
    if (list == null)
        return true;

    return list.Count == 0;
}

class Item
{
    int id;
    int Version;

    public override int GetHashCode()
    {
          unchecked
          {
                 return (Id * 397) ^ Version;
          }
    }
}
publicstaticbool为空(此IList列表)
{
if(list==null)
返回true;
返回列表。计数==0;
}
类项目
{
int-id;
int版本;
公共覆盖int GetHashCode()
{
未经检查
{
返回(Id*397)^版本;
}
}
}
我不知道为什么会这样

非常感谢您提供的任何信息

列表有时不包含任何内容,列表的计数为0。 该列表包含NHibernate项。
[NHibernate.Collection.Generic.PersistentGenericBag]

正如Shad在评论中所说,它与您的
IList的实现有关。我去查看了
PersistentGenericBag
的源代码,它看起来是这样的:

public class PersistentGenericBag<T> : PersistentBag, IList<T> { }
public class PersistentBag : AbstractPersistentCollection, IList { }
Count
属性在此类
PersistentBag
中定义,如下所示:

public int Count
{
    get { return ReadSize() ? CachedSize : bag.Count; }
}
protected virtual bool ReadSize()
{
    if (!initialized)
    {
        if (cachedSize != -1 && !HasQueuedOperations)
        {
            return true;
        }
        else
        {
            ThrowLazyInitializationExceptionIfNotConnected();
            // the below line it has to be.
            CollectionEntry entry = session.PersistenceContext.GetCollectionEntry(this); 
            ICollectionPersister persister = entry.LoadedPersister;
            if (persister.IsExtraLazy)
            {
                if (HasQueuedOperations)
                {
                    session.Flush();
                }
                cachedSize = persister.GetSize(entry.LoadedKey, session);
                return true;
            }
        }
    }
    Read();
    return false;
}
其中,
bag
是一个简单的
IList
,而
CachedSize
仅仅是一个
int
属性。所以一切都与
ReadSize
有关,它在
AbstractPersistentCollection
中定义,看起来像:

public int Count
{
    get { return ReadSize() ? CachedSize : bag.Count; }
}
protected virtual bool ReadSize()
{
    if (!initialized)
    {
        if (cachedSize != -1 && !HasQueuedOperations)
        {
            return true;
        }
        else
        {
            ThrowLazyInitializationExceptionIfNotConnected();
            // the below line it has to be.
            CollectionEntry entry = session.PersistenceContext.GetCollectionEntry(this); 
            ICollectionPersister persister = entry.LoadedPersister;
            if (persister.IsExtraLazy)
            {
                if (HasQueuedOperations)
                {
                    session.Flush();
                }
                cachedSize = persister.GetSize(entry.LoadedKey, session);
                return true;
            }
        }
    }
    Read();
    return false;
}
session
变量的类型为
ISessionImplementor
,因此一切都取决于它的实现方式。
GetCollectionEntry(bag)
应该是一个从袋子中获取物品的调用(袋子是一个允许重复元素的收集结构),在检索物品之前,袋子必须执行一些相等性检查,而袋子又必须调用物品的
GetHashCode

我不知道他们对这一切做了什么,但这与上述方法有关

参考文献:



使用堆栈跟踪查找调用方否,
列表。Count
不会调用
GetHashCode
。是什么让你这么想的?这还取决于IList的具体实现,而不是一些模糊的信息痕迹,你为什么不发布一个相关的代码来说明这个问题呢?请参阅。@MarcGravel列表是PersistentGenericBag。我想我知道发生了什么。非常感谢。由于延迟加载,PersistentGenericBag的Count属性可能会触发数据库请求。