var stack = ImmutableStack<int>. Empty;
stack = stack.Push(13);
stack = stack.Push(7);

// Wyświetla "7", a potem "13".
foreach (var item in stack)
    Trace.WriteLine(item);

int lastItem;
stack = stack.Pop(out lastItem);
// lastItem == 7

---

var stack = ImmutableStack<int>.Empty;
stack = stack.Push(13);
var biggerStack = stack.Push(7);

// Wyświetla "7", a potem "13".
foreach (var item in biggerStack)
    Trace.WriteLine(item);

// Wyświetla tylko "13".
foreach (var item in stack)
    Trace.WriteLine(item);

---

var queue = ImmutableQueue<int>.Empty;
queue = queue.Enqueue(13);
queue = queue.Enqueue(7);

// Wyświetla "13", a potem "7".
foreach (var item in queue)
    Trace.WriteLine(item);

int nextItem;
queue = queue.Dequeue(out nextItem);
// Wyświetla "13"
Trace.WriteLine(nextItem);

---

var list = ImmutableList<int>.Empty;
list = list.Insert(0, 13);
list = list.Insert(0, 7);

// Wyświetla "7", a potem "13".
foreach (var item in list)
    Trace.WriteLine(item);

list = list.RemoveAt(1);

---

// Najlepszy sposób iterowania przez ImmutableList<T>.
foreach (var item in list)
    Trace.WriteLine(item);

// To również zadziała, ale będzie znacznie wolniejsze.
for (int i = 0; i != list.Count; ++i)
    Trace.WriteLine(list[i]);

---

var hashSet = ImmutableHashSet<int>.Empty;
hashSet = hashSet.Add(13);
hashSet = hashSet.Add(7);

// Wyświetla "7" i "13" w nieprzewidywalnej kolejności.
foreach (var item in hashSet)
    Trace.WriteLine(item);

hashSet = hashSet. Remove(7);

---

var sortedSet = ImmutableSortedSet<int>.Empty;
sortedSet = sortedSet.Add(13);
sortedSet = sortedSet.Add(7);

// Wyświetla "7", a potem "13".
foreach (var item in hashSet)
    Trace.WriteLine(item);
var smallestItem = sortedSet[0];
// smallestItem == 7

sortedSet = sortedSet.Remove(7);

---

var dictionary = ImmutableDictionary<int, string>.Empty;
dictionary = dictionary.Add(10, "Dziesięć");
dictionary = dictionary.Add(21, "Dwadzieścia_jeden");
dictionary = dictionary.SetItem(10, "Diez");

// Wyświetla "10Diez" i "21Dwadzieścia_jeden" w nieprzewidywalnej kolejności.
foreach (var item in dictionary)
    Trace.WriteLine(item.Key + item.Value);

var ten = dictionary[10];
// ten == "Diez"

dictionary = dictionary.Remove(21);

---

var sortedDictionary = ImmutableSortedDictionary<int, string>.Empty;
sortedDictionary = sortedDictionary.Add(10, "Dziesięć");
sortedDictionary = sortedDictionary.Add(21, "Dwadzieścia_jeden");
sortedDictionary = sortedDictionary.SetItem(10, "Diez");

// Wyświetla "10Diez", a potem "21Dwadzieścia_jeden".
foreach (var item in sortedDictionary)
    Trace.WriteLine(item.Key + item.Value);

var ten = sortedDictionary[10];
// ten == "Diez"

sortedDictionary = sortedDictionary.Remove(21);

---

var dictionary = new ConcurrentDictionary<int, string>();
var newValue = dictionary.AddOrUpdate(0,
    key => "Zero" ,
    (key, oldValue) => "Zero");

---

dictionary[0] = "Zero";

---

string currentValue;
bool keyExists = dictionary.TryGetValue(0, out currentValue);

---

string removedValue;
bool keyExisted = dictionary.TryRemove(0, out removedValue);

---

private readonly BlockingCollection<int> _blockingQueue =
    new BlockingCollection<int>();

---

_blockingQueue.Add(7);
_blockingQueue.Add(13);
_blockingQueue.CompleteAdding();

---

// Wyświetla "7", a potem "13".
foreach (var item in _blockingQueue.GetConsumingEnumerable())
    Trace.WriteLine(item);

---

BlockingCollection<int> _blockingQueue = new BlockingCollection<int>(
    boundedCapacity: 1);

---

// To Add zostaje ukończone natychmiast.
_blockingQueue.Add(7);

// To Add czeka na usunięcie 7, zanim doda 13.
_blockingQueue.Add(13);

_blockingQueue.CompleteAdding();

---

BlockingCollection<int> _blockingStack = new BlockingCollection<int>(
    new ConcurrentStack<int>());

BlockingCollection<int> _blockingBag = new BlockingCollection<int>(
    new ConcurrentBag<int>());

---

// Kod producenta
_blockingStack.Add(7);
_blockingStack.Add(13);
_blockingStack.CompleteAdding();

// Kod konsumenta
// Wyświetla "13", a potem "7".
foreach (var item in _blockingStack.GetConsumingEnumerable())
    Trace.WriteLine(item);

---

BufferBlock<int> _asyncQueue = new BufferBlock<int>();

// Kod producenta
await _asyncQueue.SendAsync(7);
await _asyncQueue.SendAsync(13);
_asyncQueue.Complete();

// Kod konsumenta
// Wyświetla "7", a potem "13".
while (await _asyncQueue.OutputAvailableAsync())
    Trace.WriteLine(await _asyncQueue.ReceiveAsync());

---

while (true)
{
    int item;
    try
    {
        item = await _asyncQueue.ReceiveAsync();
    }
    catch (InvalidOperationException)
    {
        break;
    }
    Trace.WriteLine(item);
}

---

AsyncProducerConsumerQueue<int> _asyncQueue
    = new AsyncProducerConsumerQueue<int>();

// Kod producenta
await _asyncQueue.EnqueueAsync(7);
await _asyncQueue.EnqueueAsync(13);
await _asyncQueue.CompleteAdding();

// Kod konsumenta
// Wyświetla "7", a potem "13".
while (await _asyncQueue.OutputAvailableAsync())
    Trace.WriteLine(await _asyncQueue.DequeueAsync());

---

AsyncProducerConsumerQueue<int> _asyncQueue
    = new AsyncProducerConsumerQueue<int>(maxCount: 1);

---

// To Enqueue zostaje ukończone natychmiast.
await _asyncQueue.EnqueueAsync(7);

// To Enqueue (asynchronicznie) czeka, aż 7 zostanie usunięte,
// zanim umieści 13 w kolejce.
await _asyncQueue.EnqueueAsync(13);

await _asyncQueue.CompleteAdding();

---

while (true)
{
    var dequeueResult = await _asyncQueue.TryDequeueAsync();
    if (!dequeueResult.Success)
        break;
    Trace.WriteLine(dequeueResult.Item);
}

---

AsyncCollection<int> _asyncStack = new AsyncCollection<int>(
    new ConcurrentStack<int>());

AsyncCollection<int> _asyncBag = new AsyncCollection<int>(
    new ConcurrentBag<int>());

---

// Kod producenta
await _asyncStack.AddAsync(7);
await _asyncStack.AddAsync(13);
await _asyncStack.CompleteAddingAsync();

// Kod konsumenta
// Wyświetla "13", a potem "7".
while (await _asyncStack.OutputAvailableAsync())
    Trace.WriteLine(await _asyncStack.TakeAsync());

---

AsyncCollection<int> _asyncStack = new AsyncCollection<int>(
    new ConcurrentStack<int>(), maxCount: 1);

---

// To Add zostaje ukończone natychmiast.
await _asyncStack.AddAsync(7);

// To Add (asynchronicznie) czeka, aż 7 zostanie usunięte, zanim umieści 13 w kolejce.
await _asyncStack.AddAsync(13);

await _asyncStack.CompleteAddingAsync();

---

while (true)
{
    var takeResult = await _asyncStack.TryTakeAsync();
    if (!takeResult.Success)
        break;
    Trace.WriteLine(takeResult.Item);
}

---

BufferBlock<int> queue = new BufferBlock<int>();

// Kod producenta
await queue.SendAsync(7);
await queue.SendAsync(13);
queue.Complete();

// Kod konsumenta dla pojedynczego konsumenta
while (await queue.OutputAvailableAsync())
    Trace.WriteLine(await queue.ReceiveAsync());

// Kod konsumenta dla wielu konsumentów
while (true)
{
    int item;
    try
    {
        item = await queue.ReceiveAsync();
    }
    catch (InvalidOperationException)
    {
        break;
    }

    Trace.WriteLine(item);
}

---

BufferBlock<int> queue = new BufferBlock<int>();

// Kod producenta
queue.Post(7);
queue.Post(13);
queue.Complete();

// Kod konsumenta
while (true)
{
    int item;
    try
    {
        item = queue.Receive();
    }
    catch (InvalidOperationException)
    {
        break;
    }

    Trace.WriteLine(item);
}

---

// Kod konsumenta jest przekazywany do konstruktora kolejki.
ActionBlock<int> queue = new ActionBlock<int>(item => Trace.WriteLine(item));

// Asynchroniczny kod producenta
await queue.SendAsync(7);
await queue.SendAsync(13);

// Synchroniczny kod producenta
queue.Post(7);
queue.Post(13);
queue.Complete();

---

AsyncProducerConsumerQueue<int> queue = new AsyncProducerConsumerQueue<int>();

// Asynchroniczny kod producenta
await queue.EnqueueAsync(7);
await queue.EnqueueAsync(13);

// Synchroniczny kod producenta
queue.Enqueue(7);
queue.Enqueue(13);

queue.CompleteAdding();

// Asynchroniczny kod pojedynczego konsumenta
while (await queue.OutputAvailableAsync())
    Trace.WriteLine(await queue.DequeueAsync());

// Asynchroniczny kod wielu konsumentów
while (true)
{
    var result = await queue.TryDequeueAsync();
    if (!result.Success)
        break;
    Trace.WriteLine(result.Item);
}

// Synchroniczny kod konsumenta
foreach (var item in queue.GetConsumingEnumerable())
    Trace.WriteLine(item);
