Iterator blocks Part Four: Why no yield in catch?

Iterator blocks Part Four: Why no yield in catch?

Rate This
  • Comments 14

Now that you know why we disallow yielding in a finally, it’s pretty straightforward to see why we also disallow yielding in a catch.

First off, we still have the problem that it is illegal to “goto” into the middle of the handler of a try-protected region. The only way to enter a catch block is via the “non-local goto” that is catching an exception. So once you yielded out of the catch block, the next time MoveNext was called, we’d have no way to get back into the catch block where we left off.

Second, the exception that was thrown and caught is an intrinsic part of the execution of the catch block because it can be re-thrown using the “empty throw” syntax. We have no way of preserving that state across calls to MoveNext.

I suppose that we could in theory allow yields inside catch blocks that do not have an “empty throw”. We could turn this:

try
{
  M();
}
catch(Exception x)
{
  yield return x.ToString().Length;
  yield return 123;
}

into

switch(this.state)
{
case 0: goto LABEL0;
case 1: goto LABEL1;
case 2: goto LABEL2;
}
LABEL0:
try
{
  M(); 
  this.state = 2;
  goto LABEL2;
}
catch(Exception x)
{
  this.x = x; 
}
this.current = this.x.ToString().Length;
this.state = 1;
return true;
LABEL1:
this.current = 123;
this.state = 2;
return true;
LABEL2:
return false;

But frankly, that would be pretty weird. It would feel like a very odd restriction to disallow a fundamental part of the “catch” syntax.

And really, what’s the usage case that motivates this situation in the first place? Do people really want to try something and then yield a bunch of results if it fails? I suppose you could do something like:

IEnumerable<string> GetFooStrings(Foo foo)
{
  try
  {
    yield return Foo.Bar();
  }
  catch(InvalidFooException x)
  {
    yield return "";
  }
… etc.

but there are lots of ways to easily rewrite this so that you don’t have to yield in a catch:

IEnumerable<string> GetFooStrings(Foo foo)
{
  string result;
  try
  {
    result = Foo.Bar();
  }
  catch(InvalidFooException x)
  {
    result = "";
  }
  yield return result;
… etc.

Since there are usually easy workarounds, and we would have to put crazy-seeming restrictions on the use of re-throws, it’s easier to simply say “no yields inside a catch”.

We still haven’t explained why it is illegal to yield inside a try that has a catch, nor why it is legal to yield inside a try that has a finally. To understand why, next time I’ll need to muse about the duality between sequences and events.

  • Reading the "Generators" section of the DLR spec makes me think you are not happy with the current situation for .Net 4.0

  • Producing a good compiler error message for this case would greatly help.  The C# compiler produces decent error/warning messages but could use an update.  A VS10 feature to seend feedback on error/warning message via VS IDE would be a nice way for the VS team to produce much better compiler diagnostics.

  • It seems that the secret goal of C# is to become the most nonorthogonal language ever conceived. There are hundreds of special features and language constructs, and every one of them comes with its own long list of special rules and exceptions.

    That is not the secret goal of C#. Our stated goal is to produce high quality language tools that help pro devs solve real problems. Of course we value orthogonality of language features; orthogonal features are easier to understand, design, specify, implement, test and document. But we value usefulness above orthogonality and are willing to take the burden of corner cases in exchange for a compelling feature. We do not always make choices that everyone agrees with; if you disagree with these choices, I encourage you to propose alternate designs, or, for that matter, invent a language that does it better. I'm pro more languages. -- Eric

    After the release of C# 2.0 I thought that the priority should be to remove the remaining problems with the existing features. But instead you add more and more features to the language that are all made for one special case and useless for everything else.

    I disagree. We work hard to ensure that language features are general-purpose. For example, take LINQ. Sorting, searching, filtering, joining, grouping and projecting data are operations used in all information domains, whether you're writing a raytracer or building a three-tier business web site. -- Eric

    This is the most important issue facing C# the language, and it has been untouched since 2004 despite having a very high rating.

    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94264

    That might be the most important issue in your opinion. My opinion is that it is not an issue facing the C# language at all. This issue has nothing whatsoever to do with the language; it is a feature request for the underlying type system of the CLR. The language team has no control over that.

    That said, I had a meeting with my counterparts on the CLR team about this type system feature just two weeks ago. If they add it to the type system then we will consider doing work to surface it in the language, if we decide that doing so is a reasonable way to spend our limited budget. 

     -- Eric

    This is the most important performance problem for the CLR in general, and it has also been unhandled since 2004 despite having a very high rating.

    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=374647

    That might be the most important issue in your opinion. Again, it's nothing that has anything to do with the language. -- Eric

    This is minor compared to the issues mentioned above, but it shows the lack of attention to detail by the C# language designers. Is there any good reason why an enum should not implement IEquatable<T>?

    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=93858

    I disagree that I lack attention to detail; in fact, I am noted around here as a somewhat detail-obsessed guy. I also disagree that this has anything to do with the language. I'm sorry that the CLR is imperfect, believe me. I have to work with it every day too. But none of your concerns are anything that the language team can do anything about; try asking the CLR team.

    More generally, I understand that the "connect" site is a case of no good deed going unpunished. People asked for a site where they could provide feedback, so that's what we gave them. But because it feels like throwing ideas down a dark hole into oblivion, it produces user frustration. This is the opposite of what was intended, and I hope we can do better and mitigate some of that frustration.

    In the meanwhile, you should not think of "connect" as a democracy; we certainly take connect data into consideration when prioritizing new language and runtime features, but its not like a high number of connect votes constitutes a binding referrendum. We have many priorities for the language and runtime, priorities which always come from users, but do not necessarily come from "connect". We talk to MVPs and other industry insiders, we conduct focus groups, we have many other ways of getting real-world feedback on what people are doing. -- Eric

  • I am not as cynical as Rudiger but you have to admit orthoganlity and the predictability of feature coverage is basically "C# implements the following example". Go beyond the example even a little bit and you're off into territory charted "at your own risk".

    I have to admit no such thing because the claim is false. We carefully design features to be as orthogonal as possible, and we do our best to heavily test interactions of all possible features before we ship. -- Eric

    There is a straightforward solution to this. Allow people to run C# or F# on a file before it goes to the compiler. Line numbers stay the same, but the converter can add a bit of magic to round out the functionatliy which people expect. People would be able to see their source code while debugging, step through it, and check identifier values using the excellent debugging tools with intellisense.

    Adding full-on compile-time metaprogramming is a solution to the general problem of user-defined language features, one which we are actively researching. To handwave it away as "straightforward" is ludicrous. Adding metaprogramming will require years of design and implementation work to get right. It is not a general solution to the problem of nonorthogonality in design; I assure you, metaprogramming will introduce many new fascinating and hitherto unknown nonorthogonalities. -- Eric 

    Under the hood, things which are difficult to implement, such as calling a sub-method from an Enumerable which itself does a yield return, can be inlined to conform to the C# spec.

    I've looked at the emit and Compiler methods, but VS integration shouldn't be necessary for people using C# as their object code.  They should be able to rely upon what VS believes to be true about the assembly for intellisense and watching varialbe values.

    Here are a few fronts where I was surprised to discover non-orthogonality.  Like many developers, I have to work with about a dozen languages. None of the others tries to get away with partial feature implementations. Either the language handles a feature or it doesn't.

    If your assertion is true -- that all languages except C# provide "complete" implementations of all their features -- then either we're doing it wrong, or those languages have a pretty weak feature set. One wonders why you're still using C# if other languages are all better. The alternative is that your assertion is false. I think that if you look carefully at any nontrivial language's feature set, you'll find areas where features are not as general as they could be, or have unexpected corner cases. 

    Remember, "worse is better" -- it is usually better to have an imperfect feature that solves a real problem than to never ship at all because you can't make it perfect. -- Eric

    1: Consider returning the IEnumerable<T> type implementable with yield-return's. A fantastic language feature, until I realize my quadtree walker can't pass itself downard so that a sub-method does a yield return back up.  

    That feature is called "yield foreach". We will consider it for hypothetical future versions. -- Eric

    2. Similarly, consider lambdas. They look and feel like closures or coroutines in other languages. I'm not expecting continuations at all-- that's not C#-like and the overhead means pooling threads or using the heap as the stack. But you haven't even implemented coroutines completely.

    We haven't attempted to implement them at all, so it should not be surprising that we haven't implemented them completely. Iterators are not coroutines. Neither are lambdas. -- Eric

    3:  Consider Linq. Fantastic asset to the language. I started thinking through that lens and writing sub-methods which handle specific cases and return a result but then they aren't supposed to.  They can't return the var type. Are you saying nobody wants to return a var?

    Of course people want to return anonymous types. And they want fields of anonymous types. Doing so would involve a massive rewrite of some of the most fundamental parts of the compiler, parts that our intellisense performance depends on. It would also require driving general agreement across all managed languages about what publically exposed anonymous types look like. The proposed feature is awesome, I would love to do it, but the costs are enormous and involve cross-team and cross-company coordination. -- Eric

    4: Consider the C#4 COM Interop extensions. I can't forget who said it, but a C# expert tried to calm an irate IT guy who was concerned about the abuse of the nullable default parameters.  This feature is only for COM, someone assured them.

    That didn't sound like valuing orthogonality, but I think I get the point from a usability perspective.

    We considered making all those features only applicable in scenarios where the compiler could use a heuristic to deduce that it was talking to a COM object. The overwhelming pushback we got when we showed that design to professionals was "do the feature for everyone, not just for COM". So we did the feature orthogonally, rather than special-casing it.

    And once more, no good deed goes unpunished. We make a feature more orthogonal based on community feedback and we get publically lambasted in that community for not making it even more orthogonal.

    I'm not sure how much more orthogonal you want it to be. Nor am I clear on how exactly you expect a feature that does intense violence to overload resolution scenarios is supposed to be orthogonal to any other language feature; most of the C# language features that do semantic analysis depend in some way on overload resolution. -- Eric

    From a programmer/director  perspective, I can choose C# and .Net35 and avoid COM's from that point on because I don't like having my threading model dictated by code written before the millenium.

    Except that many applications must interop with Office. Not with COM in general, but just Office. C# could wrap the Office API and produce a far better interface from the programmer perspective.  If Office doesn't constitue at least 60% of new COM use today, then disregard this thought.

    That's not in our charter. Our job is to make language tools, not to spend even one minute analyzing the Office object model and making a really kick-ass PIA, and then documenting it, maintaining it, and dealing with the inevitable breaking changes from one version of Office to the next. If the Office team or the bizapps team wants to do that, they can do that. We make general-purpose language tools for Microsoft platforms; Office programmability is a big one, but not the only one. -- Eric

    I keep hearing about "COM objects are a fact of life" from people, but the most widely used COM's are for Microsoft Office.  Just about any functionality offered as a COM is also offered as a software library with a good API that doesn't force ref's for objects that don't get changed.  

    The fact is, if you wrapped Office with a well-designed C# API I bet you'd solve 90% of the griping about COM objects.  If the people who created COM objects are unhappy because people avoid COM, they should learn to offer their objects as a library of C# objects.  

    I'm localizing the complexity of multithreading into one class in my application. But I can't predict if it will work because it depends upon delegates and equal-signature delegates can be of distinct and unconvertable types.  

    My class has methods like "call this IEnumerable<T>(IEnumerable<T> mapper) and execute it asyncronously" and "execute this lambda statement in the GUI thread" or "excute this lambda in the COM thread".

    But if I combine C# incompelteness with the apartment threading model possibilities any COM object can have

    I have no idea whether I'm going to hit a wall where .Net Thread class asks for a StartThread object whose signature is identical to Action<object> but I can't cast one into the other. For some cases I'm forced by C# to use one delegate type, but .Net wants to enforce its own constraints.  Explicit casting won't work. In other languages delegates with the same signature can be exchanged.

    I wouldn't even mention these issues if there were a way to work around them by implementing a compiler preprocessor.  

    Feel free to invent one then, if you believe that doing so is straightforward. You should start by examining the design of Nemerle. -- Eric

    I've never had the need for try-catch-finally combined with yield return but I have often found non-orthoganlity in C# to limit my use of .Net 35 and office products.

    I think my use cases are not beyond situations which C# programmers encounter in writing complete and scalable applicatinos.  

    The point of the articles in this blog that deal with language design, and this series in particular, is that design is the art of finding reasonable compromises amongst competing alternatives while consuming limited resources. If you believe that we've made bad compromises, that's fine; not everyone has to agree with our choices. Undoubtedly we've made some bad calls along with the good ones. But if your assertion is that compromises are unnecessary, then I assure you that you're very wrong. -- Eric

  • @Michael, I see most of the points in your post, and agree with a fair number of them. Especially having a good set of interfaces for dealing with Office applications. Because I develop a fair amount of applications in this space, I have invested the time (signnificant time) to isolate "application" code from the details of the COM interfaces and it has definately paid off.

    However, one part I fail to dsee is "They can't return the var type. Are you saying nobody wants to return a var?"

    "var" is a syntactic shortcut for a strong type where the compiler can determin the actual type from the context.  In all cases, you can replace "var" with a single specific type [and there are plenty of tools that do just this].

    *IF* one could pass or return something declared as "var" then it would REQUIRE implicit "leaking" of implementation back out through the signature. Not only would this be difficult to achieve, I dont see where it would provide any value.

    The value is that you could use "extract method" on a query expression to make a helper method that returns a sequence of anonymous type. You cannot do that today because there is no way to represent the anonymous type in the return value of a method. You're forced to refactor the query to produce a nominal type first, and then extract the helper method. The down side is that doing so can impose the burden of whole-program analysis on the compiler. The language has been cleverly designed so that you can analyze all the method bodies in parallel if you choose to; var on returns would prevent that. -- Eric

  • "if you disagree with these choices, I encourage you to propose alternate designs, or, for that matter, invent a language that does it better. I'm pro more languages."

    Here is a proposal for an alternative design for C#:

    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=412848

    But apparently structural type constraints are another thing that only microsoft may use (foreach, property initializers, collection initializers), so it got closed as "wontfix".

    As you can see on the page you reference, Mads -- the C# language PM -- provided an extensive explanation of why we do not see the proposed feature as being generally useful. Apparently you disagree. We get proposed features every single day, most of which we've seen before, and most of which we reject. Believe me, you would like our product less if we took everyone's suggestions. -- Eric

    But that is still much better than acknowledging that it is a major issue, leaving it open, yet doing nothing whatsoever about it like with the arithmetic operations on generic types. If MS had closed the IArithmetic feedback item in 2004 as "wontfix", I would just have moved on to a different language (or back to C++).

    I have also been thinking about writing my own language. But I have serious doubts that I could come up with something better than scala.

    "I disagree. We work hard to ensure that language features are general-purpose. For example, take LINQ. Sorting, searching, filtering, joining, grouping and projecting data are operations used in all information domains, whether you're writing a raytracer or building a three-tier business web site."

    I have nothing against LINQ. In fact I use it all the time. But I really dislike the special SQL like syntax extension. It feels completely foreign in a C# program. It makes the language much more complex.

    The question is whether the costs of additional complexity are paid for by the increase in representational power. LINQ makes my C# programs shorter and clearer, so for me, it pays off. Apparently you disagree. -- Eric

    LINQ would have been just as useful as a library with the only language change being extension methods. Extension methods are an example of a language feature that is generally useful. But again, why are there no static extension methods or extension properties?

    We designed, implemented and cut extension properties for C# 4. We did not do a good enough job of reviewing the feature in the design phase with the constituents who were most likely to use it to solve real-world problems. When we did do so, we discovered that we had designed a feature which did not do a good job of solving their primary problem. Rather than ship a feature with a broken design, we cut it, thereby allowing us to design it properly in the future if we choose to. -- Eric 

    By the way: in scala you could write something like LINQ as a library without changing anything about the language. _That_ is a genuinely general purpose language feature.

    It is a bit of a two class situation. If microsoft thinks that X is a nice language feature, they extend the grammar of the language. Examples I could live without include the special syntax for Nullable<T>, the SQL like language extensions for LINQ, and the new dynamic keyword in C# 4.0. Every single one of those language extensions could be written as a library in scala. A large part of scala that looks like special syntax is in fact just a library.

    C# was not a language designed for end-user extensions to the syntax. If that's your requirement for a language then C# does not meet your needs. Consider scala, nemerle, maybe haskell. We are considering adding metaprogramming extensions in the future, but it will take a long time to retrofit metaprogramming into an existing language implementation.

    A design in which only the vendor has the ability to add major new syntax but third parties can ship their own class libraries has both pros and cons. You've identified the cons. The pros are that the language remains standardizable and mutually comprehensible across organizational boundaries; you can get some C# code from a colleague on a different team and have a reasonable chance of understanding its control flow. Languages which allow users to introduce their own control flow make it difficult to understand what is going on. This is particularly bad in C++. Many teams at Microsoft have written their own macro libraries that add new control flow to C++, and that code is practically incomprehensible if you don't know whats a macro and what exactly the macro does. By putting LINQ into the language, we standardize it so that everyone only has to learn it once, rather than there being a dozen competing mutually incomprehensible syntax extensions. -- Eric

    "I disagree that I lack attention to detail; in fact, I am noted around here as a somewhat detail-obsessed guy. I also disagree that this has anything to do with the language. I'm sorry that the CLR is imperfect, believe me. I have to work with it every day too. But none of your concerns are anything that the language team can do anything about; try asking the CLR team."

    C# is the main language using the CLR. So please don't tell me that the C# team does not have a major influence on the CLR team. But there are also various design decisions in C# that have nothing to do with the CLR. For example the new constructor and collection initializer syntax: it strongly encourages making pure data objects mutable. That is a really bad idea for many reasons, last but not least concurrency. And why exactly is covariance limited to interfaces?

    I agree that many new features of C# 3 encourage programming in a mutable style. We were very aware of this when we designed them. For better or for worse, OO programmers like mutating data. As you know if you've read this blog for any time, I am a big fan of immutable functional-style programming. We discuss all the time in the language design meeting how to make it easier to program in an immutable style. We also try our best to write our libraries in an immutable style; you'll notice that expression trees are immutable, for example.

    Variance is limited to interfaces and delegates because the CLR supports variance on interfaces and delegates. The CLR does not support variance on classes because its almost never typesafe. A class of T almost always has a field of type T, which means T can be used in both input and output positions, which means that T must be invariant. Since 99.9% of the time a class would have to be always either invariant or fragile, it would be foolish to add the feature. -- Eric

    "In the meanwhile, you should not think of "connect" as a democracy; we certainly take connect data into consideration when prioritizing new language and runtime features, but its not like a high number of connect votes constitutes a binding referrendum. We have many priorities for the language and runtime, priorities which always come from users, but do not necessarily come from "connect". We talk to MVPs and other industry insiders, we conduct focus groups, we have many other ways of getting real-world feedback on what people are doing."

    I exchanged email with various people at microsoft, including kevin frei and rico mariani, about the inlining limitations of the CLR. They all agreed that this is _the_ most important performance problem in the CLR. So it is not just connect feedback that points to that issue. But nothing has been done about it.

    Let's suppose you're right, and the (former) performance architect of the CLR thinks that this is the most important issue. Then I speculate that either your assertion that nothing has been done about it is incorrect, or nothing has been done about it because the performance architect of the CLR has good reasons to believe that doing something about it would cost more than the benefit accrued. But rather than you grousing and me speculating about it, why don't you ask Rico what the status of the issue is? He's not the perf architect anymore, but I'm sure he can point you at the right people. -- Eric

    About the generics limitations: every time you try to do something more than collections with generics you hit this limitation. I am certainly not the only one who noticed that you can not use operators or static methods from generics. But apparently you do not want generics to be used for more than collections/containers. Otherwise you would have fixed this issue. Another example of a language feature that is useful just for one particular application.

    I disagree. I see many usages of generics that have nothing to do with collections or containers. That said, of course containers are the primary motivating scenario for generics. -- Eric

    Anyway, it seems that MS just don't see C# as a core language for writing large applications, but rather as a language for writing glue code, database frontends and for scripting applications written in C++.

    We design C# as a core language for large application programming. We might not have succeeded in achieving that goal by the reckoning of some people. Or, we might have succeeded, but failed to provide a compelling alternative to other offerings. That's life in a competitive world; we're doing our best with the resources at our disposal, and continually trying to do better.

    Also, you might consider not trying to figure out "the opinion of Microsoft". Microsoft is composed of 90 thousand people, all of whom have their own opinions. Sussing out the "opinion of the corporation" from the behaviour of individual teams is seldom productive. -- Eric

    New APIs like Direct2D and DirectWrite are released as pure unmanaged code. There is not even a managed wrapper. There is no managed wrapper for DirectX except for the XNA game development toolkit. And as far as I could see, there are almost no managed applications in windows 7.

    I'm not following your point here.

    I appreciate that you want to use our language and framework. It's unfortunate that apparently it doesn't meet your personal standards for design, features, performance or adoption. Sadly, we are not going to delight every single one of our customers with our offerings. Thanks for your comments.

    -- Eric

  • "The computer will always understand the code, but not humans" I prefer maintainable simple code, that can be easily documented and read, rather than syntax that dissolves and disappears with languages, because the percentage of its use is very low.

    Why enter into such complexity, while what are of higher priority are the algorithm and its efficiency and code maintenance?  

    Regards

    Rabeeh

  • @Rüdiger Klaehn - You raise some interesting points. But I have to take exception with:

          "But I really dislike the special SQL like syntax extension"

    This is the "N"atural portion of the functionallity. The ability to NOT use methid/propert like system. With out this being  "I"ntegrated into the "L"anguage, it would not be LINQ, it would be just another library.

    This means that your really *dont* like LINQ, but would rather mainain a more conventional systax, which you are certainly free to do by directly invoking the class propert/methods that back LINQ....

  • Re: TheCPUWizard

    Well, then I guess I don't like LINQ. I think a language should either provide the tools for users of the language to define their own DSL (domain specific languages)/syntax candy in libraries like scala does, or not do DSLs at all. I don't like being treated like a second class citizen by a language :-)

    LINQ is not domain-specific. Sorting, searching, projecting, grouping and joining are abstractions which are generally useful in almost any conceivable domain, not narrowly tailored to a specific domain. -- Eric

  • "As you know if you've read this blog for any time, I am a big fan of immutable functional-style programming. We discuss all the time in the language design meeting how to make it easier to program in an immutable style. We also try our best to write our libraries in an immutable style; you'll notice that expression trees are immutable, for example."

    Yes, I noticed that expression trees are immutable. I also saw your posts about immutable collections. I realize that the collections library is probably another department, but what are the chances of getting an immutable collections library into the base class libraries? I have written my own immutable collections library for one project, but I would prefer to use a standard library.

    Nobody except pedants and masochists like me will ever write C# in a functional style if there is no standard immutable collections library.

    I would love to have such a thing, but as you correctly note, I'm the wrong person to ask. It's bad enough that I comment on the inchoate future of my own product; I'm certainly not going to speculate about what other teams might or might not produce in the future. -- Eric

    "Variance is limited to interfaces and delegates because the CLR supports variance on interfaces and delegates. The CLR does not support variance on classes because its almost never typesafe. A class of T almost always has a field of type T, which means T can be used in both input and output positions, which means that T must be invariant. Since 99.9% of the time a class would have to be always either invariant or fragile, it would be foolish to add the feature."

    I think I did not express precisely what I meant: If I have a class A with a method public virtual object Bla(), I should be able to override this method in a derived class with a more specific return type because it does not violate the contract. Likewise, if I have a method void Blub(string text), I should be able to override the method in a derived class with a more generic parameter like object since again it does not violate the contract.

    Especially refining return values in derived classes is extremely helpful when writing immutable class hierarchies with "clone with changes" methods. I always write stuff in that style.

    y=x.Default

      .WithName("Bla")

      .WithAge(12);

    This is generally a good way to design immutable record-like objects: instead of having a million different constructor overloads, provide a default value, and "clone with modifications" methods for each (immutable ) field..

    This feature is called return-type covariance; it is one of the most frequent feature requests we get. We have not implemented it because (1) the CLR does not support it, and (2) Anders believes that it is a bad language feature. I don't think I could succinctly and accurately summarize Anders' reasons, so I shan't attempt to do so. -- Eric

    "I'm not following your point here."

    The point is that we desperately need a fast 2D drawing API for one of our applications. WPF is much too slow because it is a retained mode framework. GDI+ is too slow since it is not hardware accelerated. And managed Direct2D is a pain since all it can draw is triangles and we don't have the time for writing our own 2d api on top of a fast triangle renderer.

    We are a .NET shop, and since .NET has been sold by MS as "the future of windows programming" I find it reasonable to assume that there will be at least a managed wrapper for important new APIs.

    I encourage you to pass on that feedback to the people who produces those APIs. -- Eric

    "I appreciate that you want to use our language and framework. It's unfortunate that apparently it doesn't meet your personal standards for design, features, performance or adoption. Sadly, we are not going to delight every single one of our customers with our offerings. Thanks for your comments."

    You are welcome. Please don't take this personally. I am just very disappointed about how C# has changed since 2.0. If the roadmap for C# had been clear in 2004 I would have simply chosen another language.

    No worries. I only take it personally when people make it personal. I frequently read about what my and my coworkers allegedly believe or what factors we allegedly did or did not consider in coming up with a particular design. These speculations are usually presented as facts, which, frankly, I resent. I particularly resent it when the alleged beliefs are in fact the opposite of what I actually believe. Part of the point of this blog is to get accurate information out there about what at least one member of the language design team actually thinks. -- Eric

  • Eric,

    Your in-line feedback on the comments is one of the things I *REALLY* appreciate, as it provides tremendous value.

    You reply about returning anonymous types (without a common declared bast type) makes sense. .....just thinking "out loud"...While I hate adding keywords (even contextually), I do wonder if it makes sense to differentiate "a named type which I choose not to explicirly name" from and anonymous type. My thinking is that if this were done, it *might* be possible to constrain the performance impact, thus allowing it to be a deliberate decision.

    I would like to discuss the issue of using aritmetic symbols on generics with you sometime. I briefly talks with Anders about it at the last MVP summit, and I think that I do have a means (basically syntactic sugar) that would be viable without changing anything under the covers...anyone interested,  feel free to ping me: david "dot" corbin "at" dynconcepts.com.

  • "I would love to have such a thing, but as you correctly note, I'm the wrong person to ask."

    That's a shame. You had no problems getting lots of new classes included into the framework class library for LINQ. So it should be possible to get an immutable List, Map and Set included as well if there is a desire for it.

    By the way: you will find that writing and using alternative collection libraries is kind of annoying since you either have to include System.Collections.Generic to get IEnumerable<T>, or always use the full name. It is currently not possible to import just a single generic class or interface.

    IEnumerable<T> is so central to the language that it should have been in the System namespace.

    "LINQ is not domain-specific. Sorting, searching, projecting, grouping and joining are abstractions which are generally useful in almost any conceivable domain, not narrowly tailored to a specific domain."

    There is a scala library for building parsers. Parsing obviously also applies to many different domains, yet Martin Odersky describes it as an "internal domain specific language" in programming in scala, page 619.

    According to wikipedia, "a domain-specific language (DSL) is a programming language or specification language dedicated to a particular problem domain, a particular problem representation technique, and/or a particular solution technique."

    LINQ is a internal mini language for querying. Of course querying is a generic concept, so it applies to many problem domains. Yet according to the above definition it is a DSL since it is dedicated to a particular problem representation and solution technique.

    I guess I just don't like the approach where microsoft decides for me which problem domains deserve their own language extensions and which don't. But as you mentioned this is "by design" in C#. That is why I find the inlining limitations of the CLR so frustrating: they prevent me from writing high performance numerical code in any CLR based language.

    "I encourage you to pass on that feedback to the people who produces those APIs."

    I already did so. But since there is such a big mismatch between what I find important and what the people making decisions at microsoft find important, I am seriously thinking about abandoning the .NET platform in the long term. And in the short term there is no way we are going to use Direct2D anyway, since we are working in a very conservative industry (space operations) and Direct2D is not available for windows XP.

    "This feature is called return-type covariance; it is one of the most frequent feature requests we get. We have not implemented it because (1) the CLR does not support it, and (2) Anders believes that it is a bad language feature. I don't think I could succinctly and accurately summarize Anders' reasons, so I shan't attempt to do so."

    If Anders does not like it, it won't happen. Which is a shame, since it is one way to make writing inheritance hierarchies of immutable objects bearable in C#.

    The other way (which we are currently using) is to let abstract base classes have a type parameter TSelf so that "clone with changes" methods can declare the proper return type. An abstract base class with a property A would have a method TSelf WithA(TA newValue). But the problem then is that there is no longer an "is a" relationship between abstract base classes and concrete classes.

    Of course you could solve this by introducing self types as a language construct, but this is such an abstract feature that there won't be any MVPs and focus groups asking for it...

  • Some comments mentiond awesome "returning anonymous types" proposed feature. Sadly it would be now even much harder to ever actualy see it in some version of C# because of including tuples in .net 4.0. Many people will be now satisfied and simply instead of (proposed):

    class Foo

    {

    public { int Min; int Max; } GetSomeResults()

    {

    return new { Min = 1, Max = 10 };

    }

    static void Test()

    {

    var results = GetSomeResults();

    Console.WriteLine("Min: (O), Max: {1}", results.Min, results.Max);

    }

    }

    will write this horrible code:

    class Foo

    {

    public Tuple<int, int> GetSomeResults()

    {

    return new Tuple<int, int>(1, 10); //Min, Max

    }

    static void Test()

    {

    var results = GetSomeResults(); //Note if you incidentally don't know: First is min, Second is max

    Console.WriteLine("Min: (O), Max: {1}", results.First, results.Second);

    }

    }

  • I just want to say I really appreciate the comment discussions. I feel enlightened.

Page 1 of 1 (14 items)