Thursday, 4 April 2013

C# ConcurrentQueue with limited number of items

public class LimitedConcurrentQueue<T> : ConcurrentQueue<T>
{
  public int Size { get; private set; }
 
  public LimitedConcurrentQueue(int size)
  {
    Size = size;
  }
 
  public new void Enqueue(T obj)
  {
    base.Enqueue(obj);
    lock (this)
    {
      while (base.Count > Size)
      {
        T outObj;
        base.TryDequeue(out outObj);
      }
    }
  }
}
 
[Test]
public void TestLimitedConcurrentQueue()
{
  var queue = new LimitedConcurrentQueue<int>(3);
  queue.Enqueue(1);
  queue.Enqueue(2);
  queue.Enqueue(3);
 
  Console.WriteLine(string.Join(",", queue.ToArray()));
  //gives 1,2,3
 
  queue.Enqueue(4);
 
  Console.WriteLine(string.Join(",", queue.ToArray()));
  //gives 2,3,4
}

Tuesday, 2 April 2013

C# LINQ inner and left outer join

Left outer join extension method is based on How to: Perform Left Outer Joins article.

[Test]
public void Test()
{
  var list1 = new List<int>() { 1, 2, 3, 4, 5}.Select(x=>new {a=x, b=x*x});
  var list2 = new List<int>() { 1, 2, 3, 4 }.Select(x => new { a = x, b = x * x * x });
 
  var innerJoin = list1.Join(list2, x => x.a, y => y.a, (x, y) => new {a = x.a, b = x.b, c = y.b});
 
  innerJoin.ForEach(Console.WriteLine);
 
  var leftOuterJoin = list1.LeftOuterJoin(list2, x => x.a, y => y.a, (x, y) => new { a = x.a, b = x.b, c = (y != null) ? y.b : (int?)null });
 
  leftOuterJoin.ForEach(Console.WriteLine);
}
public static class Extensions
{
  public static IEnumerable<TResult> LeftOuterJoin<TOuter, TInner, TKey, TResult>(
    this IEnumerable<TOuter> outer, 
    IEnumerable<TInner> inner, 
    Func<TOuter, TKey> outerKeySelector, 
    Func<TInner, TKey> innerKeySelector, 
    Func<TOuter, TInner, TResult> resultSelector)
  {
    return 
      from outerItem in outer
      join innerItem in inner on outerKeySelector(outerItem) equals innerKeySelector(innerItem) into gj
      from sub in gj.DefaultIfEmpty()
      select resultSelector(outerItem, sub);
  }
}