New Language Features in C# 2.0, Part 1
by Matthew MacDonald, coauthor of ASP.NET In a Nutshell, 2nd edition04/05/2004
Four years ago, a new upstart language named C# surprised the development world with its elegance and consistency. Now that Microsoft has released a technology preview version of Visual Studio 2005 (formerly codenamed Whidbey), .NET's favorite language is back with some new innovations. In this two-part series, you'll get a first look at three of the four major language refinements in the latest version of C#.
Anonymous Methods
In .NET programming, every executable line of code takes place inside of a method, and every method is explicitly declared at the class level -- until now. In C# 2.0, you can declare a method inside of another piece of code, where a delegate is expected. This embedded method is called an anonymous method. (Anonymous methods will look familiar to you if you've used lambda functions in the Lisp programming language.)
Anonymous methods are primarily useful if you want to quickly hook up an event handler. For example, here's the standard way to hook up an event handler that responds to the click of a button (in any version of .NET):
public partial class Form1 : Form
{
// This method connects the event handler.
public Form1()
{
InitializeComponent();
button1.Click += new EventHandler(ButtonClick);
}
// This is the event handling method.
private void ButtonClick(object sender, EventArgs e)
{
MessageBox.Show("You clicked the button.");
}
}
In this example, there are two methods. Form1() initializes the window and
connects the event handlers. ButtonClick() receives the event when the user
clicks the button.
Here's how you could rewrite this example using an anonymous method:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += delegate(object sender, EventArgs e)
{
// The following code is part of an anonymous method.
MessageBox.Show("You clicked the button, and " +
"This is an anonymous method!");
};
}
}
Notice that the event handler method is defined inside of Form1(), and is attached directly to the Click event. The anonymous method starts with the keyword
delegate, followed by the parameter list and then the actual method code.
Essentially, the Form1() method defines a new method, but doesn't execute it. (In
this example, the code in the anonymous method won't run until the Click event
fires.)
When you declare an anonymous method, the C# compiler has some liberty to
decide how it handles the situation. In this example, the compiler creates a new,
uniquely named method in the Form1 class. This anonymous method has
access to all the public and private member variables and properties of the
Form1 class.
|
Related Reading Programming C# |
Even more interestingly, the anonymous method also has access to local variables defined in the procedure where the anonymous method is declared. Here's an example that shows this somewhat counterintuitive ability:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string tempVar = "TEST";
button1.Click += delegate(object sender, EventArgs e)
{
MessageBox.Show("tempVar contains " + tempVar);
};
}
}
To make this work, the C# compiler handles this code a little differently. It
actually creates a new class that it nests inside of the Form1 class. It adds the
anonymous method to the new class, along with a private member variable to store
the contents from tempVar.
You don't need to attach an anonymous method to an event. You can also declare an anonymous method and assign it to a delegate variable. This technique is useful if you need to pass a delegate as a callback, or if you want to attach the same anonymous method to two event handlers, as shown here:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Declare the delegate that points to an anonymous method.
EventHandler clickHandler =
delegate(object sender, EventArgs e)
{
MessageBox.Show("You clicked the button, and " +
"This is an anonymous method!");
};
// Attach the delegate to two events.
button1.Click += clickHandler;
button2.Click += clickHandler;
}
}
Overall, anonymous methods make most sense if your method code is relatively short; otherwise, it can be difficult to distinguish the embedded anonymous method code from the surrounding method code. One reason you might want to use anonymous methods is to simplify the handling of asynchronous events. Using an anonymous method, you can define how you want to handle the completion of an asynchronous task in the same context where you start the asynchronous task. This approach can clarify your code.
Iterators
Often, developers need to create classes that support enumeration. When a
class supports enumeration, you can use the convenient foreach syntax to
step through a group of items. For example, if you create an OrderCatalog class
that contains a group of OrderItem instances, you might want to enumerate over
all of the items using this code:
foreach (item OrderItem in catalog)
{
// (Process OrderItem here.)
}
This code gets translated by the C# compiler to use the GetEnumerator()
method of the class. Technically, it looks like this:
Enumerator e = catalog.GetEnumerator();
while (e.MoveNext())
{
OrderItem item = e.Current;
// (Process OrderItem here.)
}
As a result, this pattern only works with classes that implement the
IEnumerable interface. Creating a class that supports enumeration in C# 1.0
ranges from mildly inconvenient to annoyingly awkward. In C# 2.0, a new language
feature known as iterators makes it much easer to create classes that
support enumeration. Instead of building a state machine to keep track of your
position in a collection, you create one public method named GetEnumerator()
that returns all of the values directly using the new yield return keyword.
For example, here's a simple class that yields three pieces of information:
public class DecoratingColors
{
public string WallPaint;
public string Carpet;
public string Furniture;
public IEnumerator<string> GetEnumerator()
{
yield return WallPaint;
yield return Carpet;
yield return Furniture;
}
}
When you use foreach on a DecoratingColors instance, you'll wind up
with three strings, one after the other.
To see the real rewards of iterators, you need to consider a more realistic
example. The following code shows the OrderCatalog class, which contains a
private collection of OrderItem instances. In this example, the GetEnumerator() method traverses all the items in the private collection in a loop, returning
one item each time.
public class OrderCatalog
{
private ArrayList orderItems = new ArrayList();
public void Load()
{
// Fill collection for a test.
orderItems.Clear();
orderItems.Add(new OrderItem("Item 1"));
orderItems.Add(new OrderItem("Item 2"));
orderItems.Add(new OrderItem("Item 3"));
}
public IEnumerator<OrderItem> GetEnumerator()
{
foreach (OrderItem item in orderItems)
{
yield return item;
}
}
}
public class OrderItem
{
private string name;
public string Name
{
get { return name; }
}
public OrderItem(string name)
{
this.name = name;
}
}
Here's the code that puts this example to the test:
OrderCatalog catalog = new OrderCatalog();
catalog.Load();
foreach (OrderItem item in catalog)
{
MessageBox.Show(item.Name);
}
The beauty of iterators is that the enumerable class can concentrate on providing information, while the consumer can concentrate on retrieving it. Neither part needs to worry about the actual implementation details of how positioned is maintained.
Partial Classes
Partial classes give you the ability to split a single class into more than one source code (.cs) file. Here's what a partial class looks like when it's split over two files:
// Stored in file MyClass1.cs
public partial class MyClass
{
public MethodA()
{...}
}
// Stored in file MyClass2.cs
public partial class MyClass
{
public MethodB()
{...}
}
When you build the application, Visual Studio .NET tracks down each piece of
MyClass and assembles it into a complete, compiled class with two methods,
MethodA() and MethodB().
Partial classes don't offer much in the way of solving programming problems, but they can be useful if you have extremely large, unwieldy classes. (Of course, this might be a sign that you haven't properly factored your problem, in which case you should really break your class down into separate classes.) The real purpose of partial classes in .NET is to hide automatically generated designer code.
For example, if you build a .NET form in Visual Studio 2005, your event-
handling code is placed in the source code file for the form, but the designer
code that creates and configures each control and connects the event handlers is
nowhere to be seen. In order to see this code, you need to select Project-->Show All Files from the Visual Studio menu. When you do, a new file appears with
the other half of the class. For example, if you create a new form named Form1,
you'll actually wind up with a Form1.cs file for your code and a
Form1.Designer.cs file that contains the automatically generated part.

Summary
In the next article in this series, you'll learn about the sexiest new language feature in C# (and no, it isn't multiple inheritance). In the meantime, for a more detailed look at the C# language rules, surf to the C# language page at MSDN, at msdn.microsoft.com/vcsharp/team/language. You'll find a link that allows you to download a detailed white paper on the new C# language specifications, along with useful insight from the C# language designers in the "Ask a Language Designer" section of the site.
Matthew MacDonald is a developer, author, and educator in all things Visual Basic and .NET. He's worked with Visual Basic and ASP since their initial versions, and written over a dozen books on the subject, including The Book of VB .NET (No Starch Press) and Visual Basic 2005: A Developer's Notebook (O'Reilly). His web site is http://www.prosetech.com/.
Return to ONDotnet.com
- Trackback from downloading-mp3-site.tripod.com
downloading mp3 song
2005-08-03 18:14:53 [View]
- Trackback from legal-download-mp3.tripod.com
legal mp3 download
2005-08-03 18:14:51 [View]
- Trackback from lord-of-life.sharelex.com
lord of life
2005-07-29 18:58:51 [View]
- Trackback from large-professor.sharelex.com
large professor
2005-07-29 18:58:12 [View]
- Trackback from http://www.kellemeshusvetiunnepeket.com/0001654.php
szemben webfejlesztõ fizetõképes adatok beállításai
2005-07-24 09:33:01 [View]
- Trackback from http://blogs.msdn.com/oallen/archive/2005/07/06/436339.aspx
VSTS Unit Testing and DotNetUsers.org
2005-07-06 21:20:05 [View]
- Trackback from http://shemnon.com/speling/archives/000152.html
Iterating multiple soap responses with Yield Return
2004-04-22 20:57:22 [View]
- Trackback from http://matt.blogs.it/2004/04/21.html#a1413
C# new features
2004-04-21 10:07:35 [View]
- Trackback from http://samgentile.com/blog/archive/2004/04/20/11449.aspx
New and Notable 47
2004-04-20 05:16:19 [View]
- Trackback from http://www.martinmay.net/archives/000013.php
C# 2.0: A Look Ahead
2004-04-07 14:31:07 [View]
- Trackback from http://weblogs.asp.net/pleloup/archive/2004/04/07/109097.aspx
New Language Features in C# 2.0
2004-04-07 09:14:18 [View]
-
Failing example code
2004-04-06 04:00:28 mcavigelli [View]


