The future track of the C# language


If you’ve heard about the new C#/Linq work that got announced today, but don’t know where to go to find it.  Well, the awesome folks at MSDN have put up a great page that highlights what we’re working on, as well as providing great links to our latest specs as well as awesome videos that show off what this is all about.  In th enext few days i’ll start going over this information in depth to give you an idea of what all the pieces are and how they all fit together.


Comments (25)

  1. Jeff Parker says:

    Arrrg Cyrus slow down, you know me and my love for the microsoft bloggers C# and .net, you just picked a bad week for the PDC. I am in a "going dark phase of production" Boss has me sending all calls to voice mail grumble’s Ok next PDC you guys need to schedule it around my schedule.

    Actually keep it up, Rss bandit I keep marking posts as unread, so expect some questions later when I get a chance to keep up.

  2. First pass of feedback – there’ll be more I’m sure.

    First off, these features are FANTASTIC. I read the spec document with my jaw on the floor the whole way. I want to say "that’s the coolest thing I’ve ever seen" about every single feature, except of course that’s mutually exclusive…

    A few comments, though:

    1) Why is it required that the members of an anonymous class be implicitly typed? Why isn’t new {int Count = 2} supported? Sure, it’s redundant in that case, but consider:

    var a = new {string Name = "avalue"};

    var b = new {string Name = null};

    Sure, you can always do a cast, but that’s uglier.

    2) I’m fairly sure I disagree with making the order of properties significant in anonymous class equivalence. The only given reason is reflection and I don’t see that as important enough – reflection doesn’t always match exactly what the language sees anyway. Just sort them alphabetically first, or something.

    3) Why do extension methods (which btw are currently my #1 contender for the "coolest" title) have to be in a class? Sounds silly, but we *are* inventing new syntax here after all. Why not just allow these methods to float within a namespace? The class name doesn’t get used for anything after all.

    4) What would be really, really cool would be if extension methods worked polymorphically. I can’t figure out if this is the case from the spec, yet.

    static void SayMe(this object o) {

    Console.WriteLine("Object");

    }

    static void SayMe(this int i) {

    Console.WriteLine("Int " + i);

    }

    static void SayMe(this object[] arr) {

    Console.WriteLine("Array:");

    foreach (var o in arr) {o.SayMe();}

    }

    new object[] {1, new object(), 3}.SayMe();

    // output would be:

    // Array:

    // Int 1

    // Object

    // Int 3

    In other words, the choice of which overloaded SayMe extension method to apply would be based on the *runtime* type of the object, not (just) the compiletime type. This of course allows another cool alternative to the visitor pattern and allows the implementation of "visit" to be the same for a whole chunk of the inheritance hierarchy.

    5) This may have been elaborated on during the talks but I can’t find it in any of the online stuff. The spec basically leaves Expression Trees as an unexplained footnote but if they’re doing what I think they’re doing it’s extremely clever and cool.

    var result = from p in People

    where p.Id = 1

    select p;

    Am I right that given a suitable implementation of the Where method (that takes an Expression instead of a delegate), the People class could actually translate that statement – on the fly at runtime! – into the string "select * from people where id = 1" and send that query to the database?

  3. Oh, more:

    6) The spec says that anonymous classes of the same structure are equivalent within the same "program". What does "program" mean in this context – the same Assembly, the same AppDomain, the same Process…?

    7) Can you serialize an anonymous class if its members are serializable?

    8) Is there any way to return an anonymous type from a method, or have it as the type of a property?

  4. Oh my.

    button.Click += (sender, e) => this.Close();

  5. CyrusN says:

    Stuart: Thanks for the feedback! It’s awesome, and i’ll be taking it all to the language design meetings.

    Answers, in order:

    1) "Why is it required that the members of an anonymous class be implicitly typed?"

    FOr now, just because πŸ™‚

    as you yourself stated, there’s no reason to be explicit about the type (since you can always cast). So it seemed safe to make it implicit (And analogous to attribute constructors). This could easily change. I’ll send you r feedback in that you like explicitness.

  6. CyrusN says:

    Stuart: "2) I’m fairly sure I disagree with making the order of properties significant in anonymous class equivalence. The only given reason is reflection and I don’t see that as important enough – reflection doesn’t always match exactly what the language sees anyway. Just sort them alphabetically first, or something. "

    I don’t have the full justification available with me, but i’m fairly sure it’s because there are cases when a user will want them to be different based on what they’re doing.

    Here’s the thing: if you make order not matter, then you can’t make our model work in a situation where you want order to matter.

    However, if you make order matter, thenyou can make our model work in a situation where you don’t want order to matter (i.e. you manually make sure you keep the same order of properties yourself).

  7. CyrusN says:

    Stuart:

    "3) Why do extension methods (which btw are currently my #1 contender for the "coolest" title) have to be in a class? Sounds silly, but we *are* inventing new syntax here after all. Why not just allow these methods to float within a namespace? The class name doesn’t get used for anything after all. "

    There’s a very good reason for that. If you’ve read the spec you can see that extension methods are *always* chosen *last* in case there are any actual instance methods that match the overload resolution. i.e. you type:

    customers.Where(…)

    and if the customers object actually has a "Where" method, then that will get called instead of the extension method.

    By making the extension method a standard static method, then it means that you can always type:

    Sequence.Where(customers, …)

    to get around the lookup issue.

  8. CyrusN says:

    Stuart:

    "4) What would be really, really cool would be if extension methods worked polymorphically. I can’t figure out if this is the case from the spec, yet. "

    Yup. That would be cool (and it was what i was referring to when i mentioned multi methods).

    Unfortunately, that’s far outside what they are currrently capable of. It’ll be somethign that will have to be discussed. It’s not clear how something like that would work without actual runtime support. i.e. currently you’d have to synthesize some sort of method that would do the dispatch appropriately.

  9. CyrusN says:

    Stuart:

    "This may have been elaborated on during the talks but I can’t find it in any of the online stuff. The spec basically leaves Expression Trees as an unexplained footnote but if they’re doing what I think they’re doing it’s extremely clever and cool.

    var result = from p in People

    where p.Id = 1

    select p;

    Am I right that given a suitable implementation of the Where method (that takes an Expression instead of a delegate), the People class could actually translate that statement – on the fly at runtime! – into the string "select * from people where id = 1" and send that query to the database?

    "

    Yes, that’s exactly it. I’ll go deeply into it in a later post. Basically it allows you to capture the C# code that was written into an object that can be introspected at *runtime*. This is exactly how DLinq works. It translates the lambda expressions you use into SQL, and then sends tht SQL to the DB.

  10. CyrusN says:

    Stuart:

    "6) The spec says that anonymous classes of the same structure are equivalent within the same "program". What does "program" mean in this context – the same Assembly, the same AppDomain, the same Process…? "

    Within the same assembly.

  11. CyrusN says:

    Stuart:

    "7) Can you serialize an anonymous class if its members are serializable? "

    I believe so. πŸ™‚

    I’ll check asap.

  12. CyrusN says:

    Stuart:

    "8) Is there any way to return an anonymous type from a method, or have it as the type of a property? "

    Yes/No. As the type is anonymous, you can’t ever refer to it except with "Var". But var is only allowed with local variables. So you can’t refer to the type when writing the return type of a method.

    However, you can pass the object in/out of a method. It’s justa an object after all, so you can just do this:

    var v = new { … }

    object o = v;

    return o;

    Not sure how helpful this is to you.

  13. Thong Nguyen says:

    OMFG.

    Microsoft rocks. I’ve been wondering if Microsoft would go the more functional route and you guys have done it! I’ve been heavily critical of C# but this is just AWESOME. C# 3.0 *IS* the wakeup call for Java and Java developers out there.

    BTW, I don’t think it’s a good idea to move extension methods out of classes. They should be thought of as "static class methods" first, and instance-like extensions second. It’s important that the host class have a proper name for interoperability with other .NET languages.

  14. Cyrus, thanks for the detailed answers! πŸ™‚

    Going through them one at a time and then more feedback at the end:

    1) Yes, I like explicitness, at least as an option πŸ™‚ Thanks for forwarding on that feedback.

    2) Hmmm… not sure. I’ll be interested to see what some of the scenarios are where you really want things to be incompatible based solely on the ordering. (My gut feeling is "just don’t try to assign them to each other then!" but I can’t back that up until I know what the scenarios actually are). If you would dig up that rationale when things have calmed down a bit, I’d love to hear what you guys had in mind here.

    3) Fair enough. You could bypass that by just providing a different syntax, eg allowing the method name to be used raw in the namespace (System.Query.Where(…) or whatever it is). But I don’t feel particularly strongly about it, and putting it in a class has another benefit… keep reading…

    4) Actually (to my great surprise) this multimethod-like feature turns out to be easypeasy with minimal compiler changes and no runtime support! All you need to do is examine all the extension methods with the same name defined in a particular class, a pair at a time. For each pair of methods:

    static Tr1 Foo(this T1 t, otherArgs) {…}

    static Tr2 Foo(this T2 t, otherArgs) {…}

    then if otherArgs are identical types, Tr2 is implicitly convertible to Tr1, and T2 is implicitly convertible to T1 but not vice versa, then synthesize a line of code at the beginning of the first method equivalent to:

    if (t is T2) return Foo((T2) t, otherArgs);

    Picking the order to insert these lines in, in the case where there are more than one, is left as an exercise for the reader (but isn’t hard!).

    Since it *is* so easy, I’d like to *strongly* suggest you do it before it becomes impossible to do backward-compatibly πŸ™‚

    (If you don’t like limiting this magic to only methods defined in the same class, you could say "within the same namespace and compilation unit". But that’s a little less clear – a compilation unit isn’t really a first-class concept in .NET, and you can’t say "same assembly" because the C# compiler has no say in what happens when two netmodules are combined into a single assembly. So this is what I meant by "there’s a benefit to putting them in a class").

    5) Cool!

    6) Fair enough. I think I’d prefer "same AppDomain" but I think I understand why that’s hard and don’t feel particularly strongly (although I reserve the right to think of an example where it becomes critically important, and start feeling strongly later πŸ˜‰ ).

    7) I realized that right now it would be useless to be able to serialize an anonymous type because you can’t cast back the deserialized object. But again, keep reading…

    8) It’s obviously not helpful at all because there’s no way to cast back the object into something you can actually get values out of. However, this and #7 lead to my new feedback…

    New feedback:

    9) These things lead me to conclude that I really want a way to refer to the type of an anonymous type. No, I don’t think that’s contradictory πŸ˜‰

    I’m increasingly uncomfortable with the idea that there are these strongly-typed objects that you can *only* refer to as var and can’t name explicitly at all. You can put them into an object but never get them out again, etc.

    The syntax doesn’t have to be concise – it’s *rare* that you’d want to use it, but it still would probably come up occasionally.

    I propose the following syntax:

    class {string Name, int Id}

    I’m pretty sure there’s no current legal situation where the word "class" can be followed directly by "{", so I think this is unambiguous.

    It allows you to return anonymous types from methods, cast them back from object, etc, if you really need to.

    class {string FirstName, string LastName} getMe() {

    return new {FirstName = "Stuart", LastName = "Ballard};

    }

    object o = new {Name = "Test", Id = 1};

    var x = (class {string Name, int Id}) o;

    Then the serialization scenario becomes possible too.

    10) I think inference of property types (from the return statement of the getter, as long as there is a getter) and methods (from the return statement in the body) should be allowed. In the presence of multiple return statements the type inference problem is already solved, because it’s the same as for a collection initializer. You’d have to say that things that infer to an anonymous type could only be internal or private unless you also made anonymous types equivalent across assemblies, though.

    private var id = 1;

    public var Id {get {return id;} set {id = value;}}

  15. A small counterpoint to your response to #2 – yes, you *can* manually make sure that you always keep the names in the same order, but if you’ve got a team of programmers of varying skill levels who aren’t intimately familiar with the details of the implementation, it’s certainly not *easy* to do so.

    This was one of the problems with Nullable not being really null – it’s okay once you understand the details of the implementation because you *could* jump through the hoops to test for null etc. But it’s a sharp learning curve and doesn’t do what you’d intuitively expect, which is a problem for inexperienced programmers trying to get productive with the language fast.

    And I noticed that #10 potentially introduces problems with cyclic inference. I don’t think this should be a showstopper because I’m *sure* that’s detectable.

  16. Ian Marteens says:

    I’m with Stuart regarding his #2 note. As far as I know, member declaration order isn’t important at all for all C#’s requirements. Why should it matter for anonymous class equivalence… except for (dirty) implementation purposes?

    It should be a definitive plus if expression trees could be serialized over a remote connection. Without this, the whole LINQ concept would only be useful in a local context, which is great, but that’s not all the picture. N-tier development requires dynamic query construction, so the middle tier API should be able to accept dynamic selection criteria. Right now, most people use condition strings. Expressions tree could be the solution.

  17. About polymorphic extention methods, I don’t think that you need to do this unless you also bring it to real instance methods.

    This would require extensive checks on runtime, and I don’t think that it’s ought to be so.

    Consider:

    class Demo

    {

    public void Method(object obj){ .. }

    public void Method(string str) { .. }

    }

    Right now if I do:

    new Demo().Method((object)"something");

    I get the Method(object), not the Method(string).

    This is the way it should behave.

    The way to do this on runtime /should/ be easy, IMO.

    //won’t really work

    typeof(Demo).GetMethod("Method").Invoke((object)"something")

    Which would call the correct method.

    More things that I want to see:

    Extentions method for properties and operators.

    Operators are super important because this would be the only way to add operators to interfaces.

    Extentions properties are a must have methods.

    A way to explicitly get reflection information where it’s known.

    For instance, I may want to pass a property info to a method, right now I’ve to use strings to do it. I want to be able to do something similar to typeof().

    I can see that this would be a problem with overloaded methods, though.

    Anonymous types depedant on orderring – this is just silly. What is the /reason/ you would want two types with the same number / type of properties to be different?

    This is inconsistent with the rest of the language.

    Extend the support of type inferncing beyond the local scope:

    public var Method()

    {

    return "something";

    }

    This have a lot of implications, but it’s a great productivity saver and it allows a lot of nice tricks.

    Some of the problems I can think of with this is what happens when you’ve this code:

    public var Method()

    {

    return new { Str = "Something" };

    }

    What is the return type of the method? How would I know from outside the method?

    I can see two possible way to do that:

    * Allow only static types in non-internal API, this is the best choice, I think.

    * Only allow var return types for internal methods, this is not a favoriate of mine.

    Another problem is accidently changing the return type of a method with var return type.

    I think that this would be cought very quickly, as it would cause breakage in other places, so it’s not such a big problem.

    One thing to consider is situation like this:

    public var Method(int i)

    {

    if (i%2==0)

    return new object();

    else

    return "something";

    }

    What would be the return type of the method?

    Two options, either error if they are not exactly the same type or revert to the most basic type.

    This leads me to another question, why are all the type inferencing insisting on keeping the same type?

    var array = new []{1,"something", null};

    array should be object[] , and the above should not cause an error.

    The idea is to go to the common base class (or object, of course), and it’s been successfully implemented in other languages.

    All in all, I /really/ like the new features!

  18. Ayende, a few responses (just my opinions of course)…

    1) Polymorphism *is* there on regular instance methods. That’s kind of the whole point. They’re polymorphic on "this".

    public class Super {

    public virtual void SayMe {

    Console.WriteLine("Super");

    }

    }

    public class Sub {

    public override void SayMe {

    Console.WriteLine("Sub");

    }

    }

    var arr = new Super[] {new Super(), new Sub(), new Super()};

    foreach (var v in arr) v.SayMe();

    However, typing this out did remind me that there’s important syntax that’s needed to do it – you have to declare the topmost method as "virtual" and the others as "override". So how would it be if the syntax were like this:

    public static virtual SayMore(this Super s) {

    Console.WriteLine("Very super");

    }

    public static override SayMore(this Sub s) {

    Console.WriteLine("Rather sub");

    }

    foreach (var v in arr) v.SayMore();

    That makes the implementation easier as well as making the programmer’s intentions clearer. And there’s no way it can be confused with anything else because static methods could never be virtual or override before.

    2) I think I agree about extension properties but I’m not sure what the syntax would be.

    public static int this string s.HalfLength {get {return s.Length / 2;}}

    seems a little verbose but I’m not sure what to omit.

    Extension operators I’m not so sure about. My initial reaction was "yes, absolutely!" but on thinking about it a bit more, I worry it would be abused to create unreadable code. The C# 3.0 samples I’ve seen so far are already very dense – an awful lot of information is expressed in very few characters of code. I think introducing nonstandard operators on standard types would push that beyond the point where it’s useful to the point where it’s just confusing (I’m biased, though, because I think C++ is practically unusable for that reason).

    3) A way to get the "type" of a method or property and have it return the corresponding MethodInfo or PropertyInfo is a really good idea. Needs a new keyword though which is tricky from a backward-compatibility standpoint. Something to look for solutions to, I guess.

    4) As far as why collection initializers (and the proposed inference on return types) don’t automatically go up to the common base type, I think that’s because with interfaces there can be more than one equally good base type and the CLR doesn’t support a type "IComparable & IFormattable & IConvertible & ValueType" or whatever. (Although I think earlier versions of Nemerle tried this and were unable to make it work without runtime help… possibly something for the CLR people to consider).

    The same situation applies with the ternary operator, in that you can’t do "Control c = test() ? new Button() : new DropDownList()". The one situation I really would like to see change in the ternary, and probably in collection initializers too, is I’d like to see value types automatically promoted to Nullable if null appears in the list:

    int? i = test() ? 1 : null;

    int?[] arr = new[] {1, 2, 3, null};

  19. Stuart,

    1> this is not the same thing. This is done via a totally different mechanism. Virtual table vs. runtime. I don’t /think/ there is a good way to do it efficently in the general case. Virtual table is one indirection away, and your suggestion would cause a type check, which is much slower.

    2> The syntax for extention properties could be this:

    public static int HalfLength[this string s]

    {

    get { return s.Length/2; }

    }

    Very clean, IMO.

    The parameter overloading was rammed against C# by Java people, saying that it will produce unmaintainable code. That proved to be false, so I don’t think that I’ll see a lot of people trying to do that any time soon. But when you need it, you really need it.

    3> backward compatiblity is a bitch, yes. Maybe a relaxed keyword? Like var is? If there is something with the same name on the context, issue a warning and use that.

    4> If you can’t solve it, use object.

  20. 1) I know it’s not the same thing and the mechanism is different. Extension methods are a different mechanism than regular methods anyway.

    I also appreciate that there’s a performance penalty to be paid. That’s a benefit to my revised proposal of making these "virtual extension methods" explicit. Many programmers, myself included, are willing to pay a slight performance penalty (and it’s certainly slight when your data structures are small, which is common) for more expressive, easier to read code.

    By making it explicit and only present when the programmer chooses to type "virtual" and "override", we get the best of both worlds – you, who don’t like it, don’t pay any penalty, but I, who do, can use it πŸ™‚

    2) True, much better.

    3) How about typeof(method this.foo(int))? "method", "property", "field" could be keywords only when they’re the first word inside of a typeof() statement and there’s another token afterwards before the close paren.

    4) I think that’s less useful than it could be.

    foreach (var i in new[] {1.5, "3", 6}) {

    yield return i.ToInt32();

    }

    That’s statically typesafe – each of those things implement IConvertible IIRC – so why shouldn’t it be allowed?

  21. Another possible syntax for anonymous types would be @{string Name, int Age}. I like that because it evokes @"string" and @identifier, both of which are there to mark what follows as "special" in some way. Also you could say that the "a" in the @-symbol stands for "anonymous" πŸ™‚

    There are more cool tricks you could do if you could do that.

    using Person = @{string Name, int Age};

    is a really quick and intuitive way to define make an anonymous type locally "nonymous" while still being able to use "var" on it.

    And I’m wondering whether this kind of thing might be useful:

    public class Person : @{string Name, int Age} {

    public override string ToString() {

    return Name + " (" + Age + ")";

    }

    }

    or this:

    public static string Stringify(this @{string Name, int Age} person) {

    return person.Name + " (" + person.Age + ")";

    }

    (which of course would be more readable if you used the "using" directive above instead of typing the @{} thing out fully).

  22. Stuart,

    1> I pointed out a possible problem, but your approach is a good one. I certainly can see situations where this would be useful.

    One nitpick, make them all virtual, no override, since there is not real base method to choose from.

    public static virtual int Something(this object obj)

    {

    }

    public static virtual int Something(this string str)

    {

    }

    This make it easier, at least to me.

    3> It’s not really intoative, but I would take that.

    4> In this situations you’re asking the compiler to make the wrong choice. If there are several options there, it should default to the most basic one or object. If you want something else, just specify it.

    foreach (var i in new IConvertible[] {1.5, "3", 6}) {

    yield return i.ToInt32();

    }

    About anonymous type using @{ properties }, I LIKE it.

    Really like it, I mean.

    It’s a great way to quickly specify a data holder type.

    One question, though:

    namespace something

    {

    using Person = @{string Str, int Int};

    }

    In another file, if I import the something namespace, do I get Person?

    I wouldn’t think so.

    So I would probably be better of using:

    class Person : @{string Str, int Int}

  23. δΈ‹θ½½ says:

    growing up (as much as it ever can). Wonder what year three will bring?

Skip to main content