Click here to Skip to main content
Click here to Skip to main content

Introduction to C# 3

, 13 Sep 2005
Rate this:
Please Sign up or sign in to vote.
Introduction to C# 3

Introduction

Just look at the C# 3 future, it's so pretty I want it now. Check out the videos that they have there. There is so much good stuff there, and it's only the start.  First of all, read the C# 3.0 spec [doc file], or just read the rest of the post to see the highlights.

Type Inferencing and Implicitly Typed Arrays

I got addicted to that when using Boo, it's something so simple, but it saves so much. In most cases, it means no more casting hell. Andres let it slip in a presentation about a year ago, in essence, it means:

var sum = 0;
var intArray = new [] { 1,2,3,4};
foreach ( var i in intArray )
{
    sum += i;
}

This is a very cool idea, especially since you can use it for the foreach construct, which should make for far better code. Did you notice how I declared the array? new [], without a type, the compiler just fixed it up automatically.

Extensions Methods

This is a feature that lets you add new instance methods to a class, without touching the class code and even if the class is already compiled. The idea opens up so many possibilities that it's just staggering. Fowler talked about it in Refactoring. Other languages, such as SmallTalk and Ruby already have it (SmallTalk has it for 30 years, I think), and it has proved to be a useful feature. You could add methods to System.Object, which would then be "inherited" by any object. Consider adding ToXmlString() for all objects, for instance. Or persistence to database. And no, it's not just syntactic sugar, those things are important. This mean that you're no longer at the mercy of the class designer. It's a truly powerful tool. The nicest thing about it, I think, is that it'll work with generics, so you get a host of goodness for very little effort. Here is the example from the spec:

public static class Sequence{
            public static IEnumerable<S> Select<T,S>(
                        this IEnumerable<T> source, Func<T,S> selector)
            {
                        foreach (T element in source) yield return selector(element);
            }
            public static IEnumerable Select<T,S>(
                        this IEnumerable source, Func<T,S> selector)
            {
                        foreach (T element in source) yield return selector(element);
            }
} 

What does the above say? Well, it means that you can now use Select() on any object that implements IEnumerable. You could even use them on your 1.0 and 1.1 collections! Can you say goodness? This is cool on so many levels that it's not even funny.

Here is another nice thing that you can do:

public static class ExtermalObjectMethods
{
    public static bool IsNull(this object obj)
    {
         return obj == null;
    }
}
object nullObj = null;
if (nullObj.IsNull() )
   Console.WriteLine("Object is null");

Just how cool is that?

Extension properties, events and operators are currently considered, but not yet supported. I certainly hope that Microsoft will implement those, as they would allow a much nicer syntax for a lot of things (an IsNull property, for a start). Adding operators to interfaces is another big problem that this can solve.

Lambda Expressions

This is like anonymous methods, only with an even easier syntax. This is something that I don't think most .NET developers will appreciate now, but they certainly would two years from now, when the functional goodness will be fully entranced. Here is how you would extract all the names from a list of customers:

string[] names = GetListOfCustomers().Select( c => c.Name );

Can you see the beauty of it? The "c => c.Name" is the lambda expression, which is just a way to tell the compiler to do the dirty work, instead of having to do it ourselves using anonymous delegates. If it was all that they were good for, they wouldn't amount to much, but they have quite a few other usages, as you'll see shortly.

Object and Collection Initializers

This is something that we had for quite some time in attributes, which is now coming to both object initialization and collections initialization. The idea is actually very simple, consider the class Person:

var ayende = new Person{Name = "Ayende", Surname = "Rahien"};
var persons = new List<Person> { 
    new Person{Name = "Ayende", Surname = "Rahien"}, 
    new Person{Name = "Foo", Surname = "Bar"}
} 

Just consider the shear amount of code that you would've to write in order to do the same today (or even in 2.0).

Anonymous Types

No, it's not Java's anonymous classes, but it's a nice enough feature. It means that you can declare a type by just using it.

var ayende = new {Name = "ayende", WebSite = http://www.ayende.com/};
Console.WriteLine(ayende.WebSite);

This would create a new type with Name and WebSite properties. While this may save some typing in certain cases, I'm not certain that this is a useful feature. You cannot use it outside of a method's boundary, since it has no type that you can access.

This is nice, but I don't like the way it's implemented now. Boo has something similar, but since Boo has type inferencing throughout the language there it actually makes sense, since it allows to return a strongly typed object from a  method, instead of an object array. Here is the Boo example:

def MethodThatReturnSeveralArgs():
    return tuple { Int: 1, Name: "Ayende", Null: null, TimeStamp: DateTime.Now}

print MethodThatReturnSeveralArgs().Name 

Since declaring variables using the var syntax is limited to local variables, I think this is unnecessarily limited.

Query Expressions

I expect this to be the big thing for C# 3, just as generics are the big thing for C# 2. The idea is to allow an SQL like syntax for selecting objects from a database/memory/XML directly into the language. The idea is quite involved, and I'm sure it will generate a lot of discussion. The idea is to be able to do the following:

var payingCustomers = from c in db.Customers
where c.Orders.Count > 0 
select new { Email = c.Email, Name = c.Name };
foreach (var c in payingCustomers)
{
   SendDiscountOffer(c.Email, c.Name);
}

There are all sorts of ways where you can plug into this statement and do all sorts of cool things with it. db.Customers may be an in memory class, or it can redirect the query to database, to remote machine, etc. This is also apparently the use case for anonymous types, as return types from lambda expressions. It's nice, but it's not enough. It should be expanded to regular methods as well, in my opinion. I suggest checking the spec anyway, I'm just touching the edge here, and I'm sure that there are a lot of cool implementations that I'm missing here.

Expression Trees

They are a way to turn lambda expressions into data. The idea is to be able to do this:

var valuedCustomers = session.Select(x => x.IsValued==true); 

What is this? Well, what happened here is that we saved the lambda expression "x => x.IsValued==true" and passed it to a persistence layer, which would parse the expression, and load from the database all the rows for which the expression is true.

The important thing here is that the Select method is not using a opaque string, but code that can be type checked and verified by the compiler. Presumably refactoring tools for C# 3 will also support this, so it will make life even easier.

For the author of the Select() method, life would be much easier as well. He won't have to parse strings, but rather deal with an AST tree. From experience, I know that dealing with ASTs is not the easiest thing in the world, but it's certainly much better than dealing with strings.

Summary

All in all, I really like the direction that C# 3 is heading for. Functional programming is not appropriate all the time, but it can save quite a bit of typing and a lot of awkward syntax. I'm very excited about the new abilities, and I think that they will present a quantum leap much bigger than 1.1 -> 2.0. Considering that those are just the language enhancements, I can hardly grasp the amount of goodness we will get in the class library and the associated tools.

I expect quite a lot of noise about query expressions (yes, they are cool). And a lot of activity in the area of lambda expressions as data, since it's a cool way to express much more than just ORM syntax.

The future is bright indeed.

History

  • 13th September, 2005: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

No Biography provided

Comments and Discussions

 
GeneralMy vote of 4 Pinmemberrushijoshi25-May-11 0:25 
QuestionMore readable ??? PinmemberHumanOsc1-Sep-06 5:58 
AnswerRe: More readable ??? PinmemberWillemM3-Jun-07 7:01 
AnswerRe: More readable ??? Pinmemberzvkeber@yahoo.com22-Aug-07 7:51 
AnswerRe: More readable ??? PinmentorKeith Barrow5-Sep-12 10:08 
Questionnull.IsNull? PinmemberNcTrun10-Jul-06 8:20 
AnswerRe: null.IsNull? PinmemberAyende @ Rahien10-Jul-06 10:41 
AnswerRe: null.IsNull? PinmemberJudah Himango21-Jul-06 5:09 
GeneralRe: null.IsNull? PinmemberNcTrun21-Jul-06 7:20 
GeneralRe: null.IsNull? PinmemberD_Guidi22-Mar-07 5:06 
GeneralExpression Trees PinmemberVladD315-Sep-05 8:18 
GeneralRe: Expression Trees PinsussAnonymous15-Sep-05 8:29 
GeneralRe: Expression Trees PinmemberVladD315-Sep-05 11:53 
QuestionLambda expressions Pinmemberdan neely14-Sep-05 7:22 
AnswerRe: Lambda expressions PinmemberKeith Farmer14-Sep-05 7:35 
AnswerRe: Lambda expressions PinmemberAyende @ Rahien14-Sep-05 8:30 
GeneralRe: Lambda expressions Pinmemberdan neely14-Sep-05 10:01 
GeneralRe: Lambda expressions PinmemberJudah Himango1-Sep-06 5:16 
GeneralType Inference PinmemberGary Thom14-Sep-05 3:01 
Personally this
 
var sum = 0;
 
makes me shudder. It reminds me too much of VB, it must be my C++ background, but I think stronger typing is better than looser typing.
 
Gary
 
Marc Clifton: "In other words, VB is like a bad parent. It can really screw up your childhood."
GeneralRe: Type Inference PinmemberDaniel Grunwald14-Sep-05 3:31 
GeneralRe: Type Inference PinmemberGary Thom14-Sep-05 4:10 
GeneralRe: Type Inference PinmemberAnders Dalvander14-Sep-05 4:57 
GeneralRe: Type Inference PinmemberGary Thom14-Sep-05 6:04 
GeneralRe: Type Inference PinmemberAnders Dalvander14-Sep-05 6:44 
GeneralRe: Type Inference PinmemberGary Thom14-Sep-05 6:52 
GeneralRe: Type Inference Pinmemberdan neely14-Sep-05 7:32 
GeneralRe: Type Inference PinmemberGary Thom14-Sep-05 8:07 
GeneralRe: Type Inference Pinmemberdan neely14-Sep-05 9:42 
GeneralRe: Type Inference PinmemberLeslie Sanford14-Sep-05 10:06 
GeneralRe: Type Inference PinmemberJoshua Quick14-Sep-05 7:09 
GeneralRe: Type Inference PinmemberJudah Himango21-Feb-06 7:10 
GeneralRe: Type Inference PinmemberJoshua Quick21-Feb-06 7:55 
GeneralRe: Type Inference PinmemberJudah Himango21-Feb-06 8:13 
GeneralRe: Type Inference PinmemberOakman20-Sep-05 0:41 
GeneralRe: Type Inference PinmemberDaniel Grunwald21-Sep-05 3:12 
GeneralRe: Type Inference PinmemberOakman21-Sep-05 12:11 
GeneralNot another C++ PinmemberPaul Selormey13-Sep-05 13:45 
GeneralRe: Not another C++ PinmemberAyende @ Rahien13-Sep-05 13:51 
GeneralRe: Not another C++ Pinmemberleppie13-Sep-05 14:10 
GeneralRe: Not another C++ PinmemberKeith Farmer13-Sep-05 14:33 
GeneralRe: Not another C++ PinmemberPaul Selormey13-Sep-05 14:53 
GeneralRe: Not another C++ PinmemberKeith Farmer13-Sep-05 15:12 
GeneralRe: Not another C++ PinmemberPaul Selormey13-Sep-05 18:56 
GeneralRe: Not another C++ Pinmembernorm.net14-Sep-05 0:22 
GeneralRe: Not another C++ PinmemberKaveh Shahbazian21-Nov-05 20:11 
GeneralRe: Not another C++ PinmemberPaul Selormey13-Sep-05 14:23 
GeneralRe: Not another C++ Pinsusskempf13-Sep-05 16:33 
GeneralRe: Not another C++ PinmemberPaul Selormey13-Sep-05 18:40 
GeneralRe: Not another C++ PinmemberKeith Farmer14-Sep-05 7:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 13 Sep 2005
Article Copyright 2005 by Ayende @ Rahien
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid