Sunday, December 21, 2008

Predicates, Action, lambdas and extension


public class Product
{
public string Category{get;set;}
public string Name { get; set; }
public decimal Price { get; set; }
}
public class Products:IEnumerable
{
public List _products;

public Products()
{

_products = new List();
}

public void Add(Product p)
{
_products.Add(p);
}

public decimal TotalPrice(Predicate match)
{
if (match==null)
throw new ArgumentNullException();

decimal totalPrice = 0;
int itemCount = _products.Count;
for (int i = 0; i < itemCount; i++)
{
if (match(_products[i]) == true)
totalPrice += _products[i].Price;

}
return totalPrice;
}


public void ForEach(Action action)
{

for (int i = 0; i < _products.Count; i++)
{
action(_products[i]);

}


}



#region IEnumerable Members

public IEnumerator GetEnumerator()
{
this._products.GetEnumerator();
}

#endregion

#region IEnumerable Members

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
this.GetEnumerator();
}

#endregion
}



extensions:


public static class MyExtensions
{
public static int MyCount(this IEnumerable list)
{
return list.Count()/2;
}
}


tests:


[TestFixture]
public class PredicateLamdaActionTests
{
[Test]
public void TestNUnit()
{
//Assert.Fail();

Assert.That(true);
}

[Test]
public void FindPriceTest()
{
Products products = new Products();
products.Add(new Product() { Name = "Pear", Category = "fruit", Price = 2 });
products.Add(new Product() { Name = "Apple", Category = "fruit", Price = 3 });
products.Add(new Product() { Name = "Banana", Category = "berry", Price = 2 });
products.Add(new Product() { Name = "Blueberry", Category = "berry", Price = 2 });
products.Add(new Product() { Name = "Beans", Category = "vegetable", Price = 2 });

Assert.AreEqual(5,products.TotalPrice(p => p.Category == "fruit"));


}

[Test]
public void DoWorkOnAllTest()
{
Products products = new Products();
products.Add(new Product() { Name = "Pear", Category = "fruit", Price = 2 });
products.Add(new Product() { Name = "Apple", Category = "fruit", Price = 3 });
products.Add(new Product() { Name = "Banana", Category = "berry", Price = 2 });
products.Add(new Product() { Name = "Blueberry", Category = "berry", Price = 2 });
products.Add(new Product() { Name = "Beans", Category = "vegetable", Price = 2 });
//products.ForEach( delegate(Product p){p.Category="fruit";});
products.ForEach(p=>p.Category="fruit");

Assert.AreEqual(11, products.TotalPrice(p => p.Category == "fruit"));


}
[Test]
public void MyCountTest()
{
Products products = new Products();
products.Add(new Product() { Name = "Pear", Category = "fruit", Price = 2 });
products.Add(new Product() { Name = "Apple", Category = "fruit", Price = 3 });
products.Add(new Product() { Name = "Banana", Category = "berry", Price = 2 });
products.Add(new Product() { Name = "Blueberry", Category = "berry", Price = 2 });
products.Add(new Product() { Name = "Beans", Category = "vegetable", Price = 2 });
Assert.AreEqual(2, products._products.MyCount());
}


}



Sunday, December 7, 2008

A Rangeable, Validated Type

As of now in .Net, we have support for Nullable types. What I really wish for is a type that would support ranges or regexes. This would enforce method calls boundaries to be well defined well defined from service oriented point of view.

Having such an ability will let us remove validation code from the method body and move it to the parameter/argument level, therefore, fixing responsibility of sending validated variables to the calling method.

If the calling method passes a variable that does not support the validation rule, an invalid argument exception is thrown!

I propose a type called ValidVariable or ValidateableVar

examples:

//ensure that only 2 digit numbers are added

public int Add2DigitNumbers(ValidVariable(10,99) first,ValidVariable(10,99) second)
{
...
}


//ensure only valid emails are supported

public void SetEmail(ValidVariable(regex_for_email))
{
...
}

If only the next version of c# supported it! or maybe I will start a project on CodePlex.

Saturday, January 12, 2008

Easiest way to sort a datatable

If it is not typed:

Dim table1,table2 as DataTable
table1 = GetDataTable()
table1.DefaultView.Sort = "ColumnName"
table2 = table1.DefaultView.ToTable()

If the DataTable is typed:

Dim table1 as MyDataTable 'MyDataTable is a strongly typed DataTable
Dim table2 as New MyDataTable()
table1 = GetDataTable()
table1.DefaultView.Sort = "ColumnName"
table2.Load(table1.DefaultView.ToTable().CreateDataReader)

As simple as that.

This may not be very efficient but is very easy :)