Visual Studio Orcas

Feel like posting Off Topic? Do it here.

Moderator: MaxCoderz Staff

Post Reply
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Visual Studio Orcas

Post by benryves »

As your local Visual Studio evangelist and Microsoft fanboy, I thought it my duty to inform you that the Express Editions of the Orcas beta are available for free download. ;)

It's based around .NET 3.5. The numbering convention might seem a little strange; unlike 2.0 to 3.0 (which merely added new class libraries), 3.0 to 3.5 adds new language features. The .NET 3.0 features (eg WPF designer) that didn't work properly in VS 2005 EE do work in the new IDE too.

New C# 3 language features. Enjoy!

EDIT: Well, I knocked together a list of examples of the new features... I think they're cool. Evidently I'm alone in that! ;)

Extension Methods

Classes and structures have a variety of exciting instance methods.
However, if a particular class is missing a method you really need, you'd have to create a new static method and call that method, passing the thing you want to act on as an argument - not very OOP!

Extension methods address this issue; just chuck your new methods into a static class using this as a special modifier on the first argument.

Code: Select all

/// <summary>Calculate the Rot13 encoded version of a string.</summary>
public static string Rot13(this string s) {
    char[] Characters = s.ToCharArray();
    for (int i = 0; i < Characters.Length; ++i) {
        int c = Characters[i];
        int d = char.ToLowerInvariant(Characters[i]);
        if (d >= 'a' && d <= 'z') {
            c += 13; d += 13;
            if (d > 'z') c -= 26;
        }
        Characters[i] = (char)c;
    }
    return new string(Characters);
}
Now all string instances which have access to the namespace that that method appears in have a new method -

Code: Select all

string s = "Hello";
MessageBox.Show(s.Rot13());
Lambda Expressions

One for the functional programming fans. These take anonymous methods a step further.

Code: Select all

Func<int, int, int> f = (x, y) => x * y;
MessageBox.Show(f(2, 3).ToString());
Doesn't look too useful like that; but suppose you passed the expression as an argument to another method...

Code: Select all

var SourceData = new int[] { 8, 5, 6, 3, 2, 7, 4 };
var EvenNumbers = SourceData.Where(i => (i & 1) == 0);
You'll notice my use of var - this new feature, implicitly typed local variables, saves your fingers. ;)
If you've ever had to type in something like this:

Code: Select all

Dictionary<int, Dictionary<string, SomeLongCustomClassName>> X = 
    new Dictionary<int, Dictionary<string, SomeLongCustomClassName>>();
...you no longer have to. :) The compiler knows what type X should be (going by what is on the right side of the expression), so you don't have to type it all in. Don't confuse this use of var with something like JavaScript's.

Object Initializers

If you've ever knocked up a class with lots of member properties, you might have seen something like this:

Code: Select all

var X = new SomeClass(10, 3, 2, "Hello", false, Fruits.Watermelon);
Problem there is you don't know what all those values map to at a glance (you need to memorise the order of the arguments), and as the author of the class you also need to create all of those different constructors. How's this?

Code: Select all

Button B = new Button {
    Text = "Hello",
    Width = 100,
    Height = 32,
    DialogResult = DialogResult.OK
};
Anonymous Types

Similar syntax can be used to create anonymous types...

Code: Select all

var x = new { Name = "Ben", Country = "England" };
x is now a type with two properties, Name and Country.

Implicitly Typed Arrays

Another one to save typing:

Code: Select all

var x = new[] { 1, 2, 3, 4, 5 };
Query Expressions

I always felt that the whole idea of passing SQL as strings to databases was rather clunky, so why not build it into the language?
Using a query expression (rather than a lambda expression) to extract even numbers from an array could look like this:

Code: Select all

var SourceData = new[] { 8, 5, 6, 3, 2, 7, 4 };
var EvenNumbers = from i in SourceData where (i & 1) == 0 orderby i select i;
User avatar
hop
Extreme Poster
Posts: 378
Joined: Sat 09 Dec, 2006 3:42 pm

Post by hop »

Glad to see that it's still free (financially at least).

I'm not so sure about the var thing. I mean it saves some typing, but it'd be nicer if you could reserve a variable name and define it later (like the way var can work in javascript). Then again I'd rather not have implicit variable typing at all. : P At least you don't have to use it.

The object initialisers are nice, though only a very minute step away from using comments (as you should). I really like it used with those anonymous types though.

Love the query expressions, want this in more languages. Though I'd really hope they'll add forcing of a nicer syntax, like having the expression encapsulated in a function.
Image
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Re: Visual Studio Orcas

Post by CoBB »

benryves wrote:Extension Methods
What do you think this is good for? Can you see class members within them? Can you overload or redefine existing methods this way?

Code: Select all

var SourceData = new int[] { 8, 5, 6, 3, 2, 7, 4 };
var EvenNumbers = SourceData.Where(i => (i & 1) == 0);
And where does the type of this function expression come from? If it compiles, how does the compiler know that i is an integer? Or is it compiled to an inefficient application of possibly overloaded operators until it is given an actual input?
benryves wrote:...you no longer have to. :) The compiler knows what type X should be (going by what is on the right side of the expression), so you don't have to type it all in.
Is this automatic type inference always possible?

Code: Select all

var SourceData = new[] { 8, 5, 6, 3, 2, 7, 4 };
var EvenNumbers = from i in SourceData where (i & 1) == 0 orderby i select i;
I’d rather prefer proper list comprehensions for their readability, but it’s a nice idea still. :)
User avatar
hop
Extreme Poster
Posts: 378
Joined: Sat 09 Dec, 2006 3:42 pm

Post by hop »

Hehe I was thinking the i would be defined elsewhere, outside of the illustrated code. Actually, I was hoping that. : P
Image
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

hop wrote:Hehe I was thinking the i would be defined elsewhere, outside of the illustrated code. Actually, I was hoping that. : P
No, it’s a lambda expression which binds i, i.e. that’s exactly where it is defined.
User avatar
hop
Extreme Poster
Posts: 378
Joined: Sat 09 Dec, 2006 3:42 pm

Post by hop »

I guess it gets int from sourcedata.
Image
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

hop wrote:I'm not so sure about the var thing. I mean it saves some typing, but it'd be nicer if you could reserve a variable name and define it later (like the way var can work in javascript).
I guess you could declare the variable as object, though with value types this adds the overhead of boxing and unboxing (albeit automatic).
The object initialisers are nice, though only a very minute step away from using comments (as you should). I really like it used with those anonymous types though.
I find it fixes the problem where a class has many properties - you don't really want to have to write a constructor for each and every combination of properties.
CoBB wrote:
benryves wrote:Extension Methods
What do you think this is good for? Can you see class members within them? Can you overload or redefine existing methods this way?
They do nothing you couldn't have already done before; like a lot of the new features they are simply syntactic sugar. So, my answer would be that if, say, you needed to perform a particular operation on a string rather than having to call a static method in a static class "manually", it's nice to just be able to use the Instance.Method() syntax that you already have with all of the other existing methods.

I tried overloading string.ToUpper(); when my new method (which really made it lowercase) was called Upper() I could call "Hello".Upper(), but renamed to ToUpper and calling "Hello".ToUpper() just called the "regular" version, with not even a compiler warning. Not sure what's going on there.

Code: Select all

var SourceData = new int[] { 8, 5, 6, 3, 2, 7, 4 };
var EvenNumbers = SourceData.Where(i => (i & 1) == 0);
And where does the type of this function expression come from? If it compiles, how does the compiler know that i is an integer? Or is it compiled to an inefficient application of possibly overloaded operators until it is given an actual input?
Simply enough; SourceData is of type IEnumerable<int>, so the .Where generic extension method takes a Func<int, bool> as an argument.

Lambda expressions are of type Func<TArg0, TArg1, ... ,TArgN, TResult>.
benryves wrote:...you no longer have to. :) The compiler knows what type X should be (going by what is on the right side of the expression), so you don't have to type it all in.
Is this automatic type inference always possible?
No, not always.
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

benryves wrote:Simply enough; SourceData is of type IEnumerable<int>, so the .Where generic extension method takes a Func<int, bool> as an argument.
Now that's confusing for a functional programmer, because we're used to the term 'filter'. ;) Or just our beloved list comprehensions:

Code: Select all

evenNumbers = [x | x <- [8,5,6,3,2,7,4], even x]
But okay, this is not a Haskell advertising topic, so I shut up. :P
User avatar
hop
Extreme Poster
Posts: 378
Joined: Sat 09 Dec, 2006 3:42 pm

Post by hop »

benryves wrote:you don't really want to have to write a constructor for each and every combination of properties.
You still have to if the constructor does more than just set local vars to passed arguments.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

CoBB wrote:Now that's confusing for a functional programmer, because we're used to the term 'filter'. ;) Or just our beloved list comprehensions:
I quite agree. At heart, C# is still an object orientated language, but has a few functional features tacked on top of it - so the syntax is never going to be ideal.

Initially, with C#1, if you wanted to pass a function around you'd have to declare a whole new named method and pass its delegate around. C#2 improved on this by adding anonymous methods, and C#3 adds the new lambda expression syntax. All that's really happening is the syntax is getting terser, no fundamental language changes.
But okay, this is not a Haskell advertising topic, so I shut up. :P
Well, I'm focussing on C#3; maybe F# would be more appropriate to functional (ML) programmers. :) I'll be honest, I've never really got into functional programming, though I do appreciate its elegance and as such am happy to see some of its features being adopted in languages based on other paradigms.
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

benryves wrote:I quite agree. At heart, C# is still an object orientated language, but has a few functional features tacked on top of it - so the syntax is never going to be ideal.
I think the two properties are largely orthogonal, so that shouldn't be a problem in itself. It's rather the evolutionary nature of language development, because it prevents radical changes between successive versions.
benryves wrote:Well, I'm focussing on C#3; maybe F# would be more appropriate to functional (ML) programmers. :) I'll be honest, I've never really got into functional programming, though I do appreciate its elegance and as such am happy to see some of its features being adopted in languages based on other paradigms.
I think the real power of functional languages can only be put into motion in lazy languages like Clean or Haskell, and it's definitely not the kind of property that would be easy to adopt in an imperative language in a straightforward way. Unfortunately the ML line of languages have strict semantics (and F# also belongs to this family), which might make them more efficient on the level of primitive operations and easier to implement, but it's harder to express sophisticated algorithms with them. If I have to choose between ML or some imperative language, I'd most likely go for the latter.
Post Reply