Alistair Findlay logo

VB.NET C# Comparison Cheat Sheet Part 3: Generics, Lambdas, Extensions and LINQ

The following is the third part of a cheat sheet to help give an overview of the differences in syntax between VB.NET and C#, in .NET 4.0. Most of the examples touch on much deeper concepts, so I’ve included a few references at the end to help you out! In particular, the LINQ section seems quite brief but this is mainly because the syntax is very similar between the two languages.

Part 3:

Previous parts:

In addition to these cheat sheets, you can also use Developer Fusion’s online conversion tool to make some comparisons of your own.

Generics

VB.NET C#
Public Class GenericClass(Of T)

	Public Sub GenericMethod(param As T)
		Debug.WriteLine("Type = " &
				param.GetType().ToString())
	End Sub

End Class
public class GenericClass<T>
{
	public void GenericMethod(T param) {
		Debug.WriteLine("Type = " +
			param.GetType().ToString());
	}
}
Dim integerGeneric As New  _
	GenericClass(Of Integer)()

' Outputs "Type = System.Int32"
integerGeneric.GenericMethod(0)
GenericClass<int> integerGeneric =
	new GenericClass<int>();

// Outputs "Type = System.Int32"
integerGeneric.GenericMethod(0);
Public Class ConstrainedClass(Of T As Control)
	Public Sub GenericMethod(param As T)
		Debug.WriteLine(param.Text)
	End Sub
End Class
public class ConstrainedClass<T> where T : Control
{
	public void GenericMethod(T param)
	{
		Debug.WriteLine(param.Text);
	}
}
Dim txt As New TextBox() With {
	.Text = "Hello!"
}

Dim tbGeneric As New  _
	ConstrainedClass(Of TextBox)
' Outputs the contents of the TextBox
tbGeneric.GenericMethod(txt)
TextBox txt = new TextBox() {
	Text = "Hello!"
};

ConstrainedClass<TextBox> tbGeneric =
	new ConstrainedClass<TextBox>();
// Outputs the contents of the TextBox
tbGeneric.GenericMethod(txt);
Public Class PaintMixer(Of T As IPaintColour)

	Public Function MixThreeColours(
		p1 As T, p2 As T, p3 As T) As T
		Return p1.Mix(p2).Mix(p3)
	End Sub

End Class
public class PaintMixer<T> where T : IPaintColour
{
	public T MixThreeColours(T p1, T p2, T p3)
	{
		return p1.Mix(p2).Mix(p3);
	}
}
Public Class ReverseSorter(Of T As List(Of Integer))

	Public Sub ReverseSort(param As T)
		param.Sort()
		param.Reverse()
	End Sub

End Class
public class ReverseSorter<T> where T : List<int>
{
	public void ReverseSort(T param)
	{
		param.Sort();
		param.Reverse();
	}
}
Public Class MultiConstrained(
	Of T As Control,
	U As {New, TextBox})

End Class
public class MultiConstrained<T, U>
	where T : Control
	where U : TextBox, new()
{

}
Dim genericList As List(Of Integer)
List<int> genericList;
Dim genericDictionary As Dictionary(Of Guid, Integer)
Dictionary<Guid, int> genericDictionary;
Dim genericLookup As Lookup(Of Guid, Integer)
Lookup<Guid, int> genericLookup;

Lambda Expressions

VB.NET C#
Delegate Sub LogTime()

Shared Sub LogTimeNow()

	Dim del As LogTime = _
		Sub() Debug.WriteLine(DateTime.Now)

	del() ' This invokes the function

End Sub
delegate void LogTime();

static void LogTimeNow()
{
	LogTime del =
		() => Debug.WriteLine(DateTime.Now);

	del(); // This invokes the function
}
Delegate Function StartsWith(param As String) As Boolean

Function StartsWithA(param As String) As Boolean

	Dim del As StartsWith = Function(x) x.StartsWith("A")
	Return del(param)

End Function
delegate bool StartsWith(string param);

bool StartsWithA(string param)
{
	StartsWith del = x => x.StartsWith("A");
	return del(param);
}
'  Alternative to above, without using delegate variable
Function StartsWithA(param As String) As Boolean

	Dim del As Func(Of String, Boolean) =
			Function(x) x.StartsWith("A")
	Return del(param)

End Function
// Alternative to above, without using delegate variable
bool StartsWithA(string param)
{
	Func<string, bool> del =
			x => x.StartsWith("A");
	return del(param);
}
Dim grub As String() =
	{"Mars bar", "Toffee Crisp", _
	"Pork pie", "Bounty"}

Dim sweets = grub.Where( _
	Function(x) x <> "Pork Pie")
string[] grub =
	{"Mars bar", "Toffee Crisp",
	"Pork pie", "Bounty"};

var sweets = grub.Where(
		x => x != "Pork pie");
' Using del lamdba from above
Dim grubBeginningWithA = grub.Where(del)
// Using del lamdba from above
var grubBeginningWithA = grub.Where(del);

Extension methods

VB.NET C#
' This is the definition of the extension

Imports System.Runtime.CompilerServices

Namespace CustomExtensions

    Public Module StringExtensions

        <Extension()>
        Public Function StartsWithA(
                ByVal param As String) As Boolean

            Return param.StartsWith("A")

        End Function

    End Module

End Namespace
// This is the definition of the extension

namespace CustomExtensions
{
    public static class StringExtensions
    {
        public static bool StartsWithA(this string param)
        {
            return param.StartsWith("A");
        }
    }
}
' Usage of the extension above

Imports CustomExtensions.StringExtensions

Public MustInherit Class MainClass

    Public Shared Function StartsWithA(
		param As String) As Boolean
        Return param.StartsWithA()
    End Function

End Class
// Usage of the extension above

using CustomExtensions;

public static class MainClass
{
    public static bool StartsWithA(string param)
    {
        return param.StartsWithA();
    }
}
Dim numbers As Integer() = {0, 1, 2, 3, 4, 5}
Dim listOfNumbers As List(Of Integer) = numbers.ToList()
int[] numbers = { 0, 1, 2, 3, 4, 5 };
List<int> listOfNumbers = numbers.ToList();
Dim first As Integer = numbers.FirstOrDefault()
int first = numbers.FirstOrDefault();

LINQ

VB.NET C#
Dim query = From n As Integer In numbers
			Where n > 3
			Select n
var query = from int n in numbers
			where n > 3
			select n;
Dim samequerywithlambda =
    numbers.Where(Function(n) n > 3)
var samequerywithlamdba =
	numbers.Where(n => n > 3);
' LINQ to XML
Dim xCrisps = <Crisps>
				  <Crisp>Ready salted</Crisp>
				  <Crisp>Salt n vinegar</Crisp>
				  <Crisp>Hedgehog</Crisp>
			  </Crisps>

Dim first As XElement =
	xCrisps.<Crisp>.FirstOrDefault()
// LINQ to XML
XElement xCrisps = new XElement("Crisps",
	new XElement("Crisp", "Ready salted"),
	new XElement("Crisp", "Salt n vinegar"),
	new XElement("Crisp", "Hedgehog")
);

XElement first = (from x in xCrisps.Elements()
					select x).FirstOrDefault();
Dim hedgehog As XElement =
	(From x In xCrisps...<Crisp>
	 Where x.Value = "Hedgehog"
	 Select x).FirstOrDefault()
XElement hedgehog =
	(from x in xCrisps.Descendants("Crisp")
	where x.Value == "Hedgehog"
	select x).FirstOrDefault();
Dim lastoneis As String =
	(From x In xCrisps...<Crisp>
	 Select "Last = " & x.Value).Last()
string lastoneis =
	(from x in xCrisps.Descendants("Crisp")
	 select "Last =  " + x.Value).Last();
Dim txtWithFirstEntry As TextBox =
	(From x In xCrisps...<Crisp>
		Select New TextBox() With
		{.Text = x.Value}).First()
TextBox txtWithFirstEntry =
	(from x in xCrisps.Descendants("Crisp")
	 select new TextBox()
	 { Text = x.Value }).First();
' LINQ to SQL or Entity Framework
Using context As New SweetsEntities()

	Dim marsBarPrice As Decimal? =
		(From c In context.Chocolates
		 Where c.Name = "Mars bar"
		 Select c.Price).FirstOrDefault()

End Using
// LINQ to SQL or Entity Framework
using (SweetsEntities context = new SweetsEntities())
{
	decimal? marsBarPrice =
		(from Chocolate c in context.Chocolates
		where c.Name == "Mars bar"
		select c.Price).FirstOrDefault();
}

References

The following links go into a bit more depth with some of the concepts above:

  • No Comments »
Comment form