2

I badly understand ConcurentQueue collection. How to use Contains method in a ConcurrentQueue if T is a class or structure?

My code:

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

How to use contains method in concurrentqueue correctly?

pragmus
  • 3,513
  • 3
  • 24
  • 46
  • [ConncurrentQueue(T) Class](http://msdn.microsoft.com/en-us/library/bb352880(v=vs.110).aspx) also here is the .Contains Example [.Contains() ConncurrentQueue](http://msdn.microsoft.com/en-us/library/bb352880(v=vs.110).aspx) – MethodMan Oct 20 '14 at 19:15
  • 1
    What are you trying to do? We don't even know why you're checking whether the queue contains `domainName`; are you trying to avoid the same name being enqueued twice? Where does the queue get emptied? What's the purpose of `domainNameCounter`, and does it matter that your design won't allow you to update it for items already in the queue? – Mike Strobel Oct 20 '14 at 19:19

3 Answers3

2

Try m_logStruct.domainNameQueue.Any(d => d.domainName == domainName)

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
1

You are passing a string while Contains method expects a DomainName. This should compile:

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

However this won't be very useful if you want to check for domainName equality. You can override Equals in 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;
    }
}
Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • 1
    Note that this will only match a DomainName member where the other field, domainNameCounter, is 0. However, this could be made to work if a) the input "parameters" actually has a domainNameCounter value to use (parsed from the string to ulong of course), and b) the new object for comparison includes that value (i.e. "new DomainName { domainName = domainName, domainNameCounter = domainNameCounter }") – Peter Duniho Oct 20 '14 at 19:19
  • 1
    Re: edit for Equals override: if you don't want to actually override the struct's built-in comparison, you could use the Contains(T, IEqualityComparer) overload instead. E.g. ".Contains(new DomainName { domainName = domainName }, Comparer.Create((d1, d2) => d1.domainName == d2.domainName))". Of course by the time one's gone to that much trouble, I think the Any() method is easier. :) Also note that there should not be any need to provide the type parameter for whichever method is used; type inference should do the right thing here. – Peter Duniho Oct 20 '14 at 19:27
1

If you only want to consider domainName field as uniquely identifying field in your queue then override Equals and GetHashCode like:

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

and then you can do:

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

Otherwise Contains will only compare the references.

If you want to include both fields domainName and domainNameCounter then include both fields in Equals and GetHashCode implementation.

If you don't want to override Equals and GetHashCode then you can't use Contains (without IEqualityComparer<DomainName>) instead you have to loop through your queue and check if any item's domainName matches your new domainName. Through LINQ you can do that using:

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

(like specified in @Peter Duniho's answer)

Community
  • 1
  • 1
Habib
  • 219,104
  • 29
  • 407
  • 436
  • @MikeStrobel, sure that can be added as `Equals(T)` is implemented, but there is no need for it with `Contains` – Habib Oct 20 '14 at 19:30
  • @MikeStrobel, fair enough. I added it. – Habib Oct 20 '14 at 19:38
  • "If you don't want to override Equals and GetHashCode then you can't use Contains": note that you can use Contains, you just have to provide an IEqualityComparer implementation along with the reference object to look for. – Peter Duniho Oct 20 '14 at 19:58