Binary search tree using stack - c#

I'm attempting to create a binary search tree without using a recursion to walk through the tree. The code attached works for initializing the tree, but when I try to walk through it, it keeps giving me the "object reference not set to instant of object" when trying to push to the stack in the GetEnumerator() method. I realize that this means I need to push an instance instead of the class itself, but how can I make an instance of "this", so to speak? Or is the only way to implement with stack is to create a separate class that holds the tree? The code is as below:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class BinarySearchTree : IEnumerable<int>
{
public int value;
public BinarySearchTree left;
public BinarySearchTree right;
Stack<BinarySearchTree> stacks;
public BinarySearchTree(int value)
{
this.value = value;
}
public BinarySearchTree(IEnumerable<int> values)
{
this.value = values.First();
foreach (var val in values.Skip(1))
{
this.Add(val);
}
}
public int Value
{
get
{
return this.value;
}
}
public BinarySearchTree Left
{
get
{
return this.left;
}
}
public BinarySearchTree Right
{
get
{
return this.right;
}
}
public void Add(int value)
{
BinarySearchTree current_node = this;
while (current_node.left != null && current_node.right != null)
{
if (value <= current_node.value)
{
current_node = current_node.left;
}
else
{
current_node = current_node.right;
}
}
if (value <= current_node.value)
{
current_node.left = new BinarySearchTree(value);
//return current_node;
}
else
{
current_node.right = new BinarySearchTree(value);
//return current_node;
}
}
public BinarySearchTree GetValueAtNode()
{
}
public IEnumerator<int> GetEnumerator()
{
BinarySearchTree current_node = this;
stacks.Push(current_node);
while (stacks.Count != 0){
if (current_node.left != null)
{
stacks.Push(current_node);
current_node = current_node.left;
}
yield return stacks.Peek().value;
current_node = stacks.Peek().right;
stacks.Pop();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
The error message is:
BinarySearchTreeTests.Can_sort_complex_tree:
Outcome: Failed
Error Message:
System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
at BinarySearchTree.GetEnumerator()+MoveNext() in c:\Users\320145763\Exercism\csharp\binary-search-tree\BinarySearchTree.cs:line 78
at BinarySearchTreeTests.Can_sort_complex_tree() in c:\Users\320145763\Exercism\csharp\binary-search-tree\BinarySearchTreeTests.cs:line 84
And the relevant unit test is:
using System.Linq;
using Xunit;
public class BinarySearchTreeTests
{
[Fact]
public void Can_sort_complex_tree()
{
var tree = new BinarySearchTree(new[] { 2, 1, 3, 6, 7, 5 });
Assert.Equal(new[] { 1, 2, 3, 5, 6, 7 }, tree.AsEnumerable());
}
}

Some issues:
The while condition in Add is not correct, it could be that just one child reference is null and that the code that follows the while loop will overwrite the existing child reference, whereby you will potentially lose part of the tree. It is probably easiest to do a while (true) and break out of the loop as soon as in the direction of choice there is no child and a new node is created to fill that gap.
stacks should not be an instance member, but a variable local to GetEnumerator as otherwise you will get two executing GetEnumerator iterators to interfere which each other's stack needs.
stacks is never initialised to be an actual Stack instance. You need new Stack<BinarySearchTree>() somewhere...
The logic of GetEnumerator is not (entirely) correct. For instance current_node = stacks.Peek().right; may assign null to current_node so that you get an exception in the next iteration.
Here is a correction to the two impacted methods:
public void Add(int value)
{
BinarySearchTree current_node = this;
while (true)
{
if (value <= current_node.value) {
if (current_node.left == null) {
current_node.left = new BinarySearchTree(value);
break;
}
current_node = current_node.left;
} else {
if (current_node.right == null) {
current_node.right = new BinarySearchTree(value);
break;
}
current_node = current_node.right;
}
}
}
public IEnumerator<int> GetEnumerator()
{
Stack<BinarySearchTree> stacks = new Stack<BinarySearchTree>();
stacks.Push(this);
while (stacks.Count != 0){
BinarySearchTree current_node = stacks.Peek();
while (current_node.left != null) {
current_node = current_node.left;
stacks.Push(current_node);
}
while (stacks.Count != 0){
current_node = stacks.Peek();
yield return current_node.value;
stacks.Pop();
if (current_node.right != null) {
stacks.Push(current_node.right);
break;
}
}
}
}

Related

Simple List Merge C# (Without Generics)

I have created a simple list class from scratch. This is for a class assignment that I have been working on for about a week - very new to lists. We can not use generics so trying to research my question below has not been fruitful. Although I did get to watch 7 tutorials on youtube by BetterCoder and I found some stuff in my book but nothing with an example of "merging".
I have three classes - my node, my list, and my program. In my list class, I am working on building a Merge() method which eventually will compare the data in the two lists and merge them into an ordered list.
Right now for some reason my Merge method - which is very basic to help me understand what is happening - is not working correctly. It has both lists passed to it, and is adding the data from listTwo to listOne BUT for some reason when it's printing to the console the second Node's Data shows twice :
EX: 1 -> 2 -> 2
instead of printing the head (1), the next (2) and then the next (3) which it should be.
EX: 1 -> 2 -> 3
In the program class I have proven with a write line that (listOne.firstNode.Next.Next.Data) = 3 . Which it should be.
Can someone help me figure out if the nodes in list one aren't pointing to each other correctly or whatever is going on?
My Merge Method must be passed both list objects (listOne and listTwo) and eventually I need to make those passed as references but I haven't figured that out quite yet and will focus on that later I suppose.
namespace LinkedList
{
//This is my Node Class
class Node
{
public object Data { get; set; }
public Node Next { get; set; }
public Node(object dataValue) : this(dataValue, null) { }
public Node(object dataValue, Node nextNode)
{
Data = dataValue;
Next = nextNode;
}
}
//This is my List Class
class List
{
public Node firstNode;
public int count;
public List()
{
firstNode = null;
}
public bool Empty
{
get { return this.count == 0; }
}
public int Count
{
get { return this.count; }
}
public object Add(int index, object o)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (index > count)
index = count;
Node current = this.firstNode;
if (this.Empty || index == 0)
{
this.firstNode = new Node(o, this.firstNode);
}
else
{
for (int i = 0; i < index - 1; i++)
current = current.Next;
current.Next = new Node(o, current.Next);
}
count++;
return o;
}
public object Add(object o)
{
return this.Add(count, o);
}
public object Merge(List a, List b)
{
a.Add(b.firstNode.Data);
return a;
}
public void Print()
{
while (this.count > 0)
{
Console.Write(firstNode.Data + "->");
if(firstNode.Next != null)
firstNode.Data = firstNode.Next.Data;
count--;
}
}
}
//And here is my Program
class Program
{
static void Main(string[] args)
{
List listOne = new List();
List listTwo = new List();
listOne.Add(1);
listOne.Add(2);
listTwo.Add(3);
listTwo.Print();
Console.WriteLine("");
listOne.Merge(listOne, listTwo);
Console.WriteLine("");
listOne.Print();
//This line below shows that the data "3" from listTwo is being added to listOne in the list Merge Method
//Console.WriteLine(listOne.firstNode.Next.Next.Data);
Console.ReadKey();
}
}
}
Actual problem in your print method
public void Print()
{
Node node = firstNode;
for (int i = 0; i < this.count; i++)
{
Console.Write(node.Data + "->");
if (node.Next != null)
node = node.Next;
}
}
Alex Sikilinda , you are right the merge method is incomplete.
public object Merge(List a, List b)
{
Node bNode = b.firstNode;
while (bNode != null)
{
a.Add(bNode.Data);
bNode = bNode.Next;
}
return a;
}
I would write it this way:
public void Merge(List b)
{
Node lastNode = GetLastNode();
if (lastNode != null)
{
lastNode.Next = b.firstNode;
}
else
{
this.firstNode = b.firstNode;
}
}
// this method is used to find the last node in current list
private Node GetLastNode()
{
if (this.firstNode == null)
{
return null;
}
Node current = this.firstNode;
while (current.Next != null)
{
current = current.Next;
}
return current;
}
First of all, I changed signature of Merge from public object Merge(List a, List b) to public void Merge(List b). Now we can use it like this:
listOne.Merge(listTwo);
This will link listOne's last element with the first element of listTwo and thus they are merged.
Now we need to change Print method since current version modifies the list, which shouldn't happen:
public void Print()
{
Node currentNode = this.firstNode;
while(currentNode != null)
{
Console.Write(currentNode.Data + ' ');
currentNode = currentNode.Next;
}
}
Instead of assigning the data back to first node I assign the
firstNode = firstNode.Next;
Please check the below Print Code
public void Print()
{
while (this.count > 0)
{
Console.Write(firstNode.Data + "->");
if (firstNode.Next != null)
firstNode = firstNode.Next;
count--;
}
}

Question about implementation of binary search tree

I am trying to learn the basics of data algorithms in C# and when implementing the below binary search tree add in process I get stuck at understanding the following: when calling the tree1.add(20); method, on the first iteration of the while loop the current.Data has the value of 50 and on the second iteration of the loop the value of the same current.Data changes to 40.
Why the value of the current.Data doesn't stuck at the value of 50 after the first iteration and what is the process by which the current.Data receives the value of 40?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BinarySearchTree
{
public class Node
{
public int Data;
public Node LeftChild;
public Node RightChild;
}
public class BinarySearchTree
{
public Node root;
public BinarySearchTree()
{
root = null;
}
public void add(int data)
{
Node newNode = new Node();
newNode.Data = data;
if (root == null)
{
root = newNode;
}
else
{
Node current = root;
Node parent;
while (true)
{
parent = current;
if (data < current.Data)
{
current = current.LeftChild;
if (current == null)
{
parent.LeftChild = newNode;
break;
}
}
else
{
current = current.RightChild;
if (current == null)
{
parent.RightChild = newNode;
break;
}
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
BinarySearchTree tree1 = new BinarySearchTree();
tree1.add(50);
tree1.add(40);
tree1.add(60);
tree1.add(20);
tree1.add(45);
tree1.add(55);
tree1.add(65);
Console.ReadLine();
}
}
}
The answer lays here:
while (true)
{
parent = current;
if (data < current.Data)
{
current = current.LeftChild; // THIS LINE
if (current == null)
{
parent.LeftChild = newNode;
break;
}
}
As you see, current is being revalued and now it is the left "child" of it self. After the first 3 add usages, the tree should look like this:
50
/ \
40 60
So first iteration - current is 50, second iteration , it goes to the left(definition of a BST) and it becomes 40 . The next iteration current will contain NULL , (The left child of 40) and will be placed inside the BST.

BInary Search Tree iterator c# without parent property

I recently started making a Binary Search Tree in C# in order to practice. After completing this task I decided to implement ICollection<T> so that my tree can be used with a foreachand just in general in order for me to practice.
I've constructed my classes in such a way that I have a Node<T> class and a BinarySearchTree<T> class that contains a Node<T> a Count integer and a IsReadOnly boolean. This is my Node Class:
internal class Node<T>: INode<T> where T: IComparable<T>
{
public Node<T> RightChildNode { get; set; }
public Node<T> LeftChildNode { get; set; }
public T Key { get; set; }
//some methods go here
}
and this is my BST class:
public class BinarySearchTree<T>: ICollection<T> where T: IComparable<T>
{
internal Node<T> Root { get; set; }
public int Count { get; private set; }
public bool IsReadOnly => false;
//some methods go here
}
Now in order to implement ICollection<T> i obviously need an enumerator which I have (partly) implemented as such:
internal class BinarySearchTreeEnumerator<T> : IEnumerator<T> where T: IComparable<T>
{
private BinarySearchTree<T> _parentTree;
private BinarySearchTree<T> _currentTree;
private Node<T> _currentNode => _currentTree.Root;
private T _currentKey;
public T Current => _currentNode.Key;
/// <summary>
/// generic constructor
/// </summary>
/// <param name="tree"></param>
public BinarySearchTreeEnumerator(BinarySearchTree<T> tree)
{
this._parentTree = tree;
}
object IEnumerator.Current => Current;
void IDisposable.Dispose(){}
//pls
public bool MoveNext()
{
if (_currentTree is null)
{
_currentTree = _parentTree;
}
var leftSubtree = this._currentTree.GetLeftSubtree();
var rightSubtree = this._currentTree.GetRightSubtree();
if (!(leftSubtree is null))
{
this._currentTree = leftSubtree;
}
else if (!(rightSubtree is null))
{
this._currentTree = rightSubtree;
}
else
{
}
}
public void Reset()
{
_currentTree = _parentTree;
}
}
now my issue is quite obviously with the MoveNext() method. It doesn't work now because what it does is it just goes down the tree on the leftmost possible path and then gets stuck when it gets to the end of that path. I know I can fix this problem by adding a Parent property to my Node<T> class and then whenever I reach the end of a path in my tree I can just go one Node up and check if there's a different path... However this would mean completely changing my original class and I would prefer not to do that.
Is this just unavoidable? Is there any way to solve this issue without changing my Node<T> class in such a way?
Edit: I Made a thing but its not working :/
public bool MoveNext()
{
if (_currentNode is null)
{
this._currentNode = _parentTree.Root;
this._nodeStack.Push(_currentNode);
return true;
}
var leftNode = this._currentNode.LeftChildNode;
var rightNode = this._currentNode.RightChildNode;
if (!(leftNode is null))
{
this._currentNode = leftNode;
this._nodeStack.Push(_currentNode);
return true;
}
else if (!(rightNode is null))
{
this._currentNode = rightNode;
this._nodeStack.Push(_currentNode);
return true;
}
else
{
//current node does not have children
var parent = this._nodeStack.Pop();
do
{
if (parent is null)
{
return false;
}
} while (!(parent.RightChildNode is null));
this._currentNode = parent.RightChildNode;
this._nodeStack.Push(_currentNode);
return true;
}
}
It might be easier to use recursion to implement this; for example:
Recursive version (for balanced trees only)
public IEnumerator<T> GetEnumerator()
{
return enumerate(Root).GetEnumerator();
}
IEnumerable<T> enumerate(Node<T> root)
{
if (root == null)
yield break;
yield return root.Key;
foreach (var value in enumerate(root.LeftChildNode))
yield return value;
foreach (var value in enumerate(root.RightChildNode))
yield return value;
}
These are members of BinarySearchTree<T>.
Given the above implementation, then the following code:
BinarySearchTree<double> tree = new BinarySearchTree<double>();
tree.Root = new Node<double> {Key = 1.1};
tree.Root.LeftChildNode = new Node<double> {Key = 2.1};
tree.Root.RightChildNode = new Node<double> {Key = 2.2};
tree.Root.LeftChildNode.LeftChildNode = new Node<double> { Key = 3.1 };
tree.Root.LeftChildNode.RightChildNode = new Node<double> { Key = 3.2 };
tree.Root.RightChildNode.LeftChildNode = new Node<double> { Key = 3.3 };
tree.Root.RightChildNode.RightChildNode = new Node<double> { Key = 3.4 };
foreach (var value in tree)
{
Console.WriteLine(value);
}
produces this output:
1.1
2.1
3.1
3.2
2.2
3.3
3.4
WARNING: Stack space is limited to 1MB for a 32-bit process and 4MB for a 64-bit process, so using recursion is likely to run out of stack space if the tree is degenerate (badly unbalanced).
Non-recursive version
You can implement the non-recursive version fairly simply, like so:
IEnumerable<T> enumerate(Node<T> root)
{
var stack = new Stack<Node<T>>();
stack.Push(root);
while (stack.Count > 0)
{
var node = stack.Pop();
if (node == null)
continue;
yield return node.Key;
stack.Push(node.RightChildNode);
stack.Push(node.LeftChildNode);
}
}
This returns the elements in the same order as the recursive version.
Since this version will not run out of stack space even for a degenerate tree, it is preferable to the recursive version.
If you add to your enumerator a
private List<Node<T>> _currentParentNodes = new List<Node<T>>();
and use it like a stack, each time you go down a level you push the current node to currentParentNodes, each time you have to go up you pop the parent node from currentParentNodes, then all your problems will pop away :-)
Do you need a depth-first-search(DFS) approach? It has a recursive nature which is hard to save as a state (it uses the call stack).
Maybe consider the broad-first-search (BFS) approach, which is iterative. You'd only need a currentNode and a Queue.
The rule would be
current = Queue.poll();
For child in current
Queue.offer(child);
At init you would do
Queue.offer(rootNode);
I apologize for my poor formatting and syntax, mobile user here.
Andres

C# Return a Copy of ConcurrentBag

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace Crystal_Message
{
class Message
{
private int messageID;
private string message;
private ConcurrentBag <Employee> messageFor;
private Person messageFrom;
private string calltype;
public Message(int iden,string message, Person messageFrom, string calltype, string telephone)
{
this.messageID = iden;
this.messageFor = new ConcurrentBag<Employee>();
this.Note = message;
this.MessageFrom = messageFrom;
this.CallType = calltype;
}
public ConcurrentBag<Employee> ReturnMessageFor
{
get
{
return messageFor;
}
}
public int MessageIdentification
{
get { return this.messageID; }
private set
{
if(value == 0)
{
throw new ArgumentNullException("Must have Message ID");
}
this.messageID = value;
}
}
public string Note
{
get { return message; }
private set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("Must Have a Message");
}
this.message = value;
}
}
public Person MessageFrom
{
get { return messageFrom; }
private set
{
this.messageFrom = value;
}
}
public string CallType
{
get { return this.calltype; }
private set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentNullException("Please specify call type");
}
this.calltype = value;
}
}
public void addEmployee(Employee add)
{
messageFor.Add(add);
}
public override string ToString()
{
return "Message: " + this.message + " From: " + this.messageFrom + " Call Type: " + this.calltype + " For: " + this.returnMessagefor();
}
private string returnMessagefor()
{
string generate="";
foreach(Employee view in messageFor)
{
generate += view.ToString() + " ";
}
return generate;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
Message testEquals = obj as Message;
if((System.Object)testEquals == null)
{
return false;
}
return (this.messageID == testEquals.messageID) && (this.message == testEquals.message) && (this.messageFor == testEquals.messageFor) && (this.messageFrom == testEquals.messageFrom) && (this.calltype == testEquals.calltype);
}
public bool Equals(Message p)
{
if ((Object)p == null)
{
return false;
}
return (this.messageID == p.messageID) && (this.message == p.message) && (this.messageFor == p.messageFor) && (this.messageFrom == p.messageFrom) && (this.calltype == p.calltype);
}
public override int GetHashCode()
{
unchecked
{
return this.messageID.GetHashCode() * 33 ^ this.message.GetHashCode() * 33 ^ this.messageFor.GetHashCode() * 33 ^ this.messageFrom.GetHashCode() * 33 ^ this.calltype.GetHashCode();
}
}
}
}
I have a Message class where a user could leave a message for more than one person. I have a getter for it, however, is returning a ConcurrentBag<> the way I've done proper practice? If not, how do i return the ConcurrentBag<> so I can loop through it and display it?
ConcurrentBag<T> is an IEnumerable<T>. You can loop through it as usual. However, as this is a thread safe collection, there are performance concerns to using it.
If you want to get rid of the performance impact while looping, call ToArray on it and return the new array instead.
public IEnumerable<Employee> ReturnMessageFor
{
get
{
return messageFor.ToArray();
}
}
It's not clear to me what you are trying to accomplish.
Are you trying to externalize the Bag for all operations? Because that's what you did...
If you want to externalize something you can iterate over you should either return the Bag as IEnumerable or return an array or a list copied from the Bag.
Either way it's safe to iterate over. Might not be the best in terms of performance, but that's another question.
// Option 1
public IEnumerable<Employee> ReturnMessageFor
{
get
{
return messageFor;
}
}
// Option 2
public Employee[] ReturnMessageFor
{
get
{
return messageFor.ToArray();
}
}
Notes:
You might want to make messageFor readonly (in the code you posted it is readonly).
Remember that a ConcurrentBag allows you to safely iterate over a snapshot of the collection in a thread safe manner, but it does not lock the items in the collection.

Why my ConcurentSet doesn't work?

I was asking for any ConcurentSet/ConcurentQueue implementation here how to create no-duplicates ConcurrentQueue? but noone suggested anything.
So I've decided to wrote it myself, modified MSDN example slightly.
I've created ConcurentSet class. I insert the same element twice, and expect it to be inserted only once, because Set is used inside:
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
However according to output elements inserted twice:
Add:0 Count=0
Add:0 Count=1
Add:1 Count=2
Add:1 Count=3
Add:2 Count=4
Take:0
Add:2 Count=5
Add:3 Count=6
Add:3 Count=7
Add:4 Count=7
Add:4 Count=8
Take:3
Add:5 Count=9
Add:5 Count=10
Add:6 Count=11
Add:6 Count=12
The question is - why my ConcurentSet implementation doesn't work as expected?
I expect such output:
Add:0 Count=0
Add:0 Count=0
Add:1 Count=1
Add:1 Count=1
Add:2 Count=2
Take:0
Add:2 Count=1
Add:3 Count=2
Add:3 Count=2
Add:4 Count=3
Add:4 Count=3
Take:3
Add:5 Count=3
Add:5 Count=3
.....
Full listing below:
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace BCBlockingAccess
{
using System;
using System.Collections.Concurrent;
public class ConcurentSet
: IProducerConsumerCollection<int>
{
private readonly object m_lockObject = new object();
private readonly HashSet<int> m_set = new HashSet<int>();
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public int Count { get { return m_set.Count; } }
public object SyncRoot { get { return m_lockObject; } }
public bool IsSynchronized { get { return true; } }
public void CopyTo(int[] array, int index)
{
throw new NotImplementedException();
}
public bool TryAdd(int item)
{
lock (m_lockObject)
{
m_set.Add(item);
}
return true;
}
public bool TryTake(out int item)
{
lock (m_lockObject)
{
foreach (var i in m_set)
{
if (m_set.Remove(i))
{
item = i;
return true;
}
}
item = -1;
return false;
}
}
public int[] ToArray()
{
throw new NotImplementedException();
}
public IEnumerator<int> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
// Increase or decrease this value as desired.
int itemsToAdd = 50;
// Preserve all the display output for Adds and Takes
Console.SetBufferSize(80, (itemsToAdd * 5) + 3);
// A bounded collection. Increase, decrease, or remove the
// maximum capacity argument to see how it impacts behavior.
BlockingCollection<int> numbers = new BlockingCollection<int>(new ConcurentSet());
// A simple blocking consumer with no cancellation.
Task.Factory.StartNew(() =>
{
int i = -1;
while (!numbers.IsCompleted)
{
try
{
i = numbers.Take();
}
catch (InvalidOperationException)
{
Console.WriteLine("Adding was compeleted!");
break;
}
Console.WriteLine("Take:{0} ", i);
// Simulate a slow consumer. This will cause
// collection to fill up fast and thus Adds wil block.
Thread.SpinWait(100000);
}
Console.WriteLine("\r\nNo more items to take. Press the Enter key to exit.");
});
// A simple blocking producer with no cancellation.
Task.Factory.StartNew(() =>
{
for (int i = 0; i < itemsToAdd; i++)
{
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
numbers.Add(i);
Console.WriteLine("Add:{0} Count={1}", i, numbers.Count);
}
// See documentation for this method.
numbers.CompleteAdding();
});
// Keep the console display open in debug mode.
Console.ReadLine();
}
}
}
BlockingCollection maintains its own count and doesn't use count of underlying ConcurrentSet of yours therefore even if duplicates are ignored, the count increases.
You might want to write your own wrapper around this collection which returns count from the concurrentset and relays every other method property to the blocking collection.

Categories