Использование Содержит метод<T> в ConcurrentQueue, если T является классом или структурой

Я плохо понимаю коллекцию ConcurentQueue. Как использовать метод Contains в ConcurrentQueue, если T является классом или структурой?

Мой код:

    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
                      {
                      }
               //...
}

Как правильно использовать метод содержит в параллельном очереди?

3 ответа

Решение

Вы передаете строку, в то время как метод Contains ожидает имя_домена. Это должно скомпилировать:

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

Однако это не будет очень полезно, если вы хотите проверить на равенство domainName. Вы можете переопределить Equals в DomainName:

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;
    }
}

Пытаться m_logStruct.domainNameQueue.Any(d => d.domainName == domainName)

Если вы только хотите рассмотреть domainName поле как уникально идентифицирующее поле в вашей очереди, а затем переопределить Equals а также GetHashCode лайк:

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 буду сравнивать только ссылки.

Если вы хотите включить оба поля domainName а также domainNameCounter затем включите оба поля в Equals а также GetHashCode реализация.

Если вы не хотите переопределять Equals а также GetHashCode тогда вы не можете использовать Contains (безIEqualityComparer<DomainName> ) вместо этого вы должны пройти через вашу очередь и проверить, есть лиdomainNameсоответствует вашему новомуdomainName, Через LINQ вы можете сделать это, используя:

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

(как указано в ответе @Peter Duniho)

Другие вопросы по тегам