Friday, May 30, 2008

A generic ListCollection<T> class

I blogged recently about using public Collection instead of public List. On The Visual Studio Code Analysis Team Blog they explained how to ensure that we could re-use List methods in our concrete instance of Collection generic class, if necessary. The catch there is that a developer has to remember to call base class constructor like

public class AddressCollection : Collection<Address> {
public AddressCollection() : base(new List<Address>()) { }
}

And I thought: why not to use generics to ensure that base class constructor is called? It works fine, I tested it:



using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq; 

namespace ProgrammerThoughts.Common {
  /// <summary>
  /// A generic Collection class which ensures that it actually contains generic List.
  /// This provides us with an ability to re-use any public method of List&lt;T&gt;
  /// with a simple shell function. Such a shell could be implemented in ListColection&lt;T&gt;.
  /// or in a concrete implermentation.
  /// </summary>
  public class ListCollection<T> : Collection<T>
    where T : class {
    public ListCollection()
      : base(new List<T>()) {
    } 

    /// <summary>
    /// You can implement such shell methods in your concrete implementations of this generic instead.
    /// </summary>
    /// <param name="match">An actual function of type Predicate&lt;T&gt;</param>
    /// <returns></returns>
    public T Find(Predicate<T> match) {
      List<T> items = (List<T>)Items;
      return items.Find(match);
    }
  }
}

Thursday, May 01, 2008

C# block scoping rules for variables, anonymous methods and lambdas

I was reading Rick Strahl's blog post about "Variable Scoping in Anonymous Delegates in C#". I added a completely wrong comment there. That happens when studying too many languages at the same time. (My only excuse is that even Rick itself wasn't entirely right.)

JavaScript, Scala, and F# allow to hide outer variable by declaring another variable with the same name in a nested scope. C# does not allow to do that!

In C# lambdas and anonymous methods are treated as inline code placed into a nested block scope. It is consistent with the fact that they can access local variables from outer scope.
Behind the scenes compiler activities of creating actual delegate object and closure behavior are what they are: behind the scenes compiler activities. They should not and do not affect lexical rules.

And those lexical scoping rules for nested blocks, anoyimous methods, and lambdas are as followed:

namespace VariableScope {
/// <summary>

/// C# 3.0 in a Nutshell, http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/
/// Page 46, "The scope of local or constant variable extends to the end of the current block.
/// You cannot declare another local variable with the same name in the current block
/// or in any nested blocks."
/// That's an opposite to JavaScript and F# scoping rules.
/// </summary>

class Program {
delegate int Adder();

static void Main(string[] args) {
int x;
{
int y;
int z;
int x; // error, x already defined in outer scope (1*)
}
int y; // error, y already defined in a child scope (2*)
{
int z; // ok, no z in outer block
}
Console.WriteLine(z); // error, z is out of scope

int t, u;
Adder goodAdder = () => { return t++; }; //ok
Adder badAdder = () => { int u; return t + u; }; // error, u already defined in outer scope
Adder badToo = delegate { int u; return t + u; }; // the same error
}
}
}
// 1*: Compiler errors are as followed
// 1 A local variable named 'x' cannot be declared in this scope because it would give
// a different meaning to 'x', which is already used in a 'parent or current' scope to denote something else
//
// 2*: Compiler error is as followed
// A local variable named 'y' cannot be declared in this scope because it would give
// a different meaning to 'y', which is already used in a 'child' scope to denote something else