Posts Tagged ‘linq’

Function Name Instead of Lambda in Linq Functions

February 8th, 2010

I did not realize that functions can fill in for predicates directly without lambda notation. To illustrate, consider the following:

void Main()
{
	var words = new List<string>()
	{
		"therapists",
		"s words",
		"slang",
		"mustache",
		"sean connery"
	};

	var s_words = words.Where(w => w.StartsWith("s" ,StringComparison.CurrentCultureIgnoreCase));

	foreach(var word in s_words)
	{
		Console.WriteLine(word);
	}
}

It works, but it’s a rather long lambda, which is why I broke it out of the for loop. Let’s put that logic into a function, getting this:

void Main()
{
	var words = new List<string>()
	{
		"therapists",
		"s words",
		"slang",
		"mustache",
		"sean connery"
	};

	foreach(var word in words.Where(w => SWords(w)))
	{
		Console.WriteLine(word);
	}
}

public bool SWords(string word)
{
	return word.StartsWith("s" ,StringComparison.CurrentCultureIgnoreCase);
}

That’s better. And you might find yourself using your test in other places in the code, so it’s useful to have the function. What I found out recently, is that you can go one step further:

void Main()
{
	var words = new List<string>()
	{
		"therapists",
		"s words",
		"slang",
		"mustache",
		"sean connery"
	};

	foreach(var word in words.Where(SWords))
	{
		Console.WriteLine(word);
	}
}

public bool SWords(string word)
{
	return word.StartsWith("s" ,StringComparison.CurrentCultureIgnoreCase);
}

In this example, the savings may not look drastic. But for several chained methods you can gain a lot of brevity and clarity.

IEnumerable and Linq

July 7th, 2009

I was helping someone on StackOverFlow.com and ran into an interesting issue. The post is here.

I explained the issue in my response, but I’ll try to sum up. Newer collection types implement IEnumerable(Of T) as opposed to the original IEnumerable interface. For example, System.Generic.List(Of T) implements IEnumerable(Of T), so the following is valid without casting:

Dim names As New Generic.List(Of String)
names.Add("Bob")
names.Add("Bill")
names.Add("Joe")
names.Add("Zeke")
Dim threeLetterNames = From name In names _
                                     Where name.Length = 3 _
                                     Select name
Dim i As Integer = 1
For Each name As String In threeLetterNames.ToList()
    Console.WriteLine("Name {0} of {1}: {2}", i, threeLetterNames.Count, name)
    i += 1
Next
Console.Read()

Because the Generic List returns strings. So “name” in the Where clause is a string.

In the original poster’s question, they were using a DataGridViewRowCollection. It implements IEnumerable. So any Linq code sees each item as an object.

Here’s what’s strange about this. The “as type” clause does not resolve the issue. In a for each loop, it does resolve it. Why does For Each compile to include a cast, and Linq does not? That’s a good question for Microsoft.