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
Anonymous
September 13, 2005
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.Anonymous
September 13, 2005
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?Anonymous
September 13, 2005
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?Anonymous
September 13, 2005
Oh my.
button.Click += (sender, e) => this.Close();Anonymous
September 13, 2005
The comment has been removedAnonymous
September 13, 2005
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).Anonymous
September 13, 2005
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.Anonymous
September 13, 2005
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.Anonymous
September 13, 2005
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.Anonymous
September 13, 2005
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.Anonymous
September 13, 2005
Stuart:
"7) Can you serialize an anonymous class if its members are serializable? "
I believe so. :)
I'll check asap.Anonymous
September 13, 2005
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.Anonymous
September 14, 2005
The comment has been removedAnonymous
September 14, 2005
The comment has been removedAnonymous
September 14, 2005
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.Anonymous
September 14, 2005
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.Anonymous
September 14, 2005
The comment has been removedAnonymous
September 14, 2005
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};Anonymous
September 15, 2005
The comment has been removedAnonymous
September 15, 2005
The comment has been removedAnonymous
September 15, 2005
The comment has been removedAnonymous
September 16, 2005
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}Anonymous
October 08, 2005
growing up (as much as it ever can). Wonder what year three will bring?Anonymous
January 20, 2008
PingBack from http://websitescripts.247blogging.info/cyrus-blather-the-future-track-of-the-c-language/Anonymous
May 31, 2009
PingBack from http://woodtvstand.info/story.php?id=2674