使用Contains<;T>;方法,如果T是类或结构

本文关键字:结构 如果 gt Contains lt 使用 方法 | 更新日期: 2023-09-27 18:27:09

我非常了解ConcurrentQueue集合。如果T是类或结构,如何在ConcurrentQueue中使用Contains方法?

我的代码:

    namespace lab2Form
    {
        struct DomainName
        {
            public string domainName;
            public ulong domainNameCounter;
        }
        class LogStruct
        {
            public ConcurrentQueue<DomainName> domainNameQueue;
            //some code
            public LogStruct()
            {
                domainNameQueue = new ConcurrentQueue<DomainName>() { };
                //some code
            }
        }
        class CLogParser
        {
            LogStruct m_logStruct;
            public CLogParser()
            {
                 m_logStruct = new LogStruct();
            }
            public void ThreadProc(object param)
            {
                //...
                string line;
                while ((line = file.ReadLine()) != null)
                {
                    var space_pos = line.IndexOf(' ');
                    if (space_pos > 0)
                    {
                      string[] parameters = line.Split(new Char[] { ' ' },            StringSplitOptions.RemoveEmptyEntries);
                      string domainName = parameters[0];
                      if (m_logStruct.domainNameQueue.Contains<DomainName>(domainName))//I can't understand how to build this code-string correctly
                      {
                      }
               //...
}

如何正确使用concurrentqueue中的contains方法?

使用Contains<;T>;方法,如果T是类或结构

尝试m_logStruct.domainNameQueue.Any(d => d.domainName == domainName)

您正在传递一个字符串,而Contains方法需要一个DomainName。这应该编译:

m_logStruct.domainNameQueue.Contains<DomainName>(new DomainName {domainName = domainName})

然而,如果你想检查域名是否相等,这将不是很有用。您可以覆盖DomainName:中的Equals

struct DomainName
{
    public string domainName;
    public ulong domainNameCounter;
    public override bool Equals(object obj)
    {
        if (obj is DomainName)
        {
            return ((DomainName) obj).domainName == domainName;
        }
        return false;
    }
}

如果只想将domainName字段视为队列中唯一的标识字段,则覆盖EqualsGetHashCode,如:

struct DomainName : IEquatable<DomainName>
{
    public string domainName;
    public ulong domainNameCounter;
    public bool Equals(DomainName other)
    {
        return string.Equals(domainName, other.domainName);
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is DomainName && Equals((DomainName) obj);
    }
    public override int GetHashCode()
    {
        return (domainName != null ? domainName.GetHashCode() : 0);
    }
}

然后你可以做:

LogStruct m_logStruct = new LogStruct();
m_logStruct.domainNameQueue.Enqueue(new DomainName() {domainName = "ABC", domainNameCounter = 1});
m_logStruct.domainNameQueue.Enqueue(new DomainName() {domainName = "DEF", domainNameCounter = 1});
if (m_logStruct.domainNameQueue.Contains(new DomainName() {domainName = "ABC", domainNameCounter = 1}))
{
    Console.WriteLine("Already exists");
}

否则,Contains将仅比较引用。

如果要同时包含字段domainNamedomainNameCounter,则在EqualsGetHashCode实现中同时包含这两个字段。

如果您不想覆盖EqualsGetHashCode,则不能使用Contains(没有IEqualityComparer<DomainName>,而是必须遍历队列,检查是否有任何项目的domainName与新的domainName匹配。通过LINQ,您可以使用:

bool ifExist = m_logStruct.domainNameQueue.Any(d => d.domainName == domainName);

(如@Peter Duniho的回答中所述)