<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Fabulous Adventures In Coding : Static Methods</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx</link><description>Tags: Static Methods</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Color Color</title><link>http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx</link><pubDate>Mon, 06 Jul 2009 16:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9762614</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9762614.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9762614</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Pop quiz: What does the following code do when compiled and run?&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;class C&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void M(string x)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("static M(string)");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void M(object s)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("M(object)");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;BR&gt;class Program&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C c = new C();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c.M("hello");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;(1) writes static M(string)&lt;BR&gt;(2) writes M(object)&lt;BR&gt;(3) uh, dude, this code doesn’t even compile much less run&lt;BR&gt;(4) something else 
&lt;P&gt;Think about that for a bit and then try it and see if you were right. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;In option (1), the compiler could decide that the best match is the static one and let you call it through the instance, ignoring the instance value. In option (2), the compiler could decide that the object version is the best match and ignore the static one, even though the argument match is better. But neither of those actually happens; the rules of C# say that the compiler should &lt;STRONG&gt;pick the best match based on the arguments&lt;/STRONG&gt;, and &lt;EM&gt;then&lt;/EM&gt; disallow static calls that are through an instance! The actual result here is therefore (3): &lt;SPAN class=code&gt;
&lt;P&gt;error CS0176: Member 'C.M(string)' cannot be accessed with an instance reference; qualify it with a type name instead &lt;/SPAN&gt;
&lt;P&gt;What is up with this craziness? If you believe that the rule “static methods should never be accessed through instances” is a good rule – and it seems reasonable – then why doesn’t overload resolution remove the static methods from the candidate set when called through an instance? Why does it even allow the “string” version to be an applicable candidate in the first place, if the compiler knows that it can never possibly work? 
&lt;P&gt;I agree that this seems really goofy at first. 
&lt;P&gt;To explain why this is not quite as dumb as it seems, consider the following variation on the problem. Class C stays the same. &lt;SPAN class=code&gt;
&lt;P&gt;class B&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; public C C = new C();&lt;BR&gt;&amp;nbsp; public void N()&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C.M("hello");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What does a call to N on an instance of B do?&lt;/P&gt;
&lt;P&gt;(1) writes static M(string)&lt;BR&gt;(2) writes M(object)&lt;BR&gt;(3) compilation error&lt;BR&gt;(4) something else&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;A bit trickier now, isn’t it? Does C.M mean “call instance method M on the instance stored in this.C?” or does it mean “call static method M on type C”? Both are applicable!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Because of our goofy rule we do the right thing in this case.&lt;/STRONG&gt; We first resolve the call based solely on the arguments and determine that the static method is the best match. Then we check to see if the “receiver” at the call site can be interpreted as being through the type. It can. So we make the static call and write “static M(string)”. &lt;STRONG&gt;If the instance version had been the best match then we would successfully call the instance method through the property.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So the reason that the compiler does not remove static methods when calling through an instance is because the compiler does not necessarily know that you are calling through an instance. Because there are situations where it is ambiguous whether you’re calling through an instance or a type, we defer deciding which you meant until the best method has been selected.&lt;/P&gt;
&lt;P&gt;Now, one could make the argument that in our first case, the receiver cannot &lt;EM&gt;possibly&lt;/EM&gt; be a type. We &lt;EM&gt;could&lt;/EM&gt; have further complicated the language semantics by having &lt;EM&gt;three&lt;/EM&gt; overload resolution rules, one for when the receiver is &lt;EM&gt;known to be a type&lt;/EM&gt;, one for when the receiver is &lt;EM&gt;known to not be a type&lt;/EM&gt;, and one for when the receiver &lt;EM&gt;might or might not be a type&lt;/EM&gt;. But rather than complicate the language further, we made the pragmatic choice of simply deferring the staticness check until after the bestness check. That’s not perfect but it is good enough for most cases and it solves the common problem.&lt;/P&gt;
&lt;P&gt;The common problem is the situation that arises when you have a&lt;STRONG&gt; property of a type with the same name&lt;/STRONG&gt;, and then try to call either a static method on the type, or an instance method on the property. (This can also happen with locals and fields, but local and field names typically differ&amp;nbsp;in case from the names of their&amp;nbsp;types.)&amp;nbsp;The canonical motivating example is a public property named Color of type Color, so we call this “&lt;STRONG&gt;the Color Color problem&lt;/STRONG&gt;”. &lt;/P&gt;
&lt;P&gt;In real situations the instance and static methods typically have different names, so in the typical scenario you never end up calling an instance method when you expect to call a static method, or vice versa. The case I presented today with a name collision between a static and an instance method is relatively rare.&lt;/P&gt;
&lt;P&gt;If you’re interested in reading the exact rules for how the compiler deals with the Color Color problem, see section 7.5.4.1 of the C# 3.0 specification. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9762614" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Puzzles/default.aspx">Puzzles</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Color+Color/default.aspx">Color Color</category></item><item><title>Why Doesn't C# Implement "Top Level" Methods?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/06/22/why-doesn-t-c-implement-top-level-methods.aspx</link><pubDate>Mon, 22 Jun 2009 18:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9797817</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>58</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9797817.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9797817</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;C# requires that every method be in some class, even if it is a static method in a static class in the global namespace. Other languages allow "top level" functions. A&lt;A class="" href="http://stackoverflow.com/questions/1024171/why-c-is-not-allowing-non-member-functions-like-c/1027853#1027853" mce_href="http://stackoverflow.com/questions/1024171/why-c-is-not-allowing-non-member-functions-like-c/1027853#1027853"&gt; recent stackoverflow post asks why that is.&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I am asked "why doesn't C# implement feature X?" all the time. The answer is always the same: because no one ever designed, specified, implemented, tested, documented and shipped that feature. All six of those things are necessary to make a feature happen. All of them cost huge amounts of time, effort and money. Features are not cheap, and we try very hard to make sure that we are only shipping those features which give the best possible benefits to our users given our constrained time, effort and money budgets.&lt;/P&gt;
&lt;P&gt;I understand that such a general answer probably does not address the specific question. &lt;/P&gt;
&lt;P&gt;In this particular case, the clear user benefit was in the past not large enough to justify the complications to the language which would ensue. By restricting how different language entities nest inside each other we (1) restrict legal programs to be in a common, easily understood style, and (2) make it possible to define "identifier lookup" rules which are comprehensible, specifiable, implementable, testable and documentable. &lt;/P&gt;
&lt;P&gt;By restricting method bodies to always be inside a struct or class, we make it easier to reason about the meaning of an unqualified identifier used in an invocation context; such a thing is always an invocable member of the current type (or a base type).&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now, JScript.NET has this feature. (And in fact, JScript.NET goes even further; you can have program statements "at the top level" too.) A reasonable question is "why is this feature good for JScript but bad for C#?"&lt;/P&gt;
&lt;P&gt;First off, I reject the premise that the feature is "bad" for C#. The feature might well be good for C#, just not &lt;EM&gt;good enough&lt;/EM&gt; compared to its costs (and to the &lt;EM&gt;opportunity cost&lt;/EM&gt; of doing that feature &lt;EM&gt;instead of a more valuable feature&lt;/EM&gt;.) The feature might become good enough for C# if its costs are lowered, or if the compelling benefit to customers becomes higher.&lt;/P&gt;
&lt;P&gt;Second, the question assumes that the feature is good for JScript.NET. Why is it good for JScript.NET?&lt;/P&gt;
&lt;P&gt;It's good for JScript.NET because JScript.NET was designed to be a "scripty" language as well as a "large-scale development" language. "JScript classic"'s original design as a scripting language requires that "a one-line program actually be one line". If your intention is to make a language that allows for rapid development of short, simple scripts by novice developers then you want to minimize the amount of "ritual incantations" that must happen in every program. In JScript you do not want to have to start with a bunch of using clauses and define a class and then put stuff in the class and have a Main routine and blah blah blah, all this ritual just to get Hello World running.&lt;/P&gt;
&lt;P&gt;C# was designed to be a large-scale application development language geared towards pro devs from day one; it was never intended to be a scripting language. It's design therefore encourages enforcing the &lt;EM&gt;immediate&lt;/EM&gt; organization of even small chunks of code into &lt;EM&gt;components&lt;/EM&gt;. &lt;STRONG&gt;C# is a component-oriented language.&lt;/STRONG&gt; We therefore want to encourage programming in a component-based style and discourage features that work against that style.&lt;/P&gt;
&lt;P&gt;This is changing. "REPL" languages like F#, long popular in academia, are increasing in popularity in industry. There's a renewed interest in "scripty" application programmability via tools like Visual Studio Tools for Applications. These forces cause us to re-evaluate whether "a one line program is one line" is a sensible goal for hypothetical future versions of C#. Hitherto it has been an explicit non-goal of the language design.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;(As always, whenever I discuss the hypothetical "next version of C#", keep in mind that we have not announced any next version, that it might never happen, and that it is utterly premature to think about feature sets or schedules. All speculation about future versions of unannounced products should be taken as "for entertainment purposes only" musings, not as promises about future offerings.)&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;We are therefore &lt;EM&gt;considering&lt;/EM&gt; adding this feature to a hypothetical future version of C#, in order to better support "scripty" scenarios and REPL evaluation. When the existence of powerful new tools is predicated upon the existence of language features, that is points towards getting the language features done.&lt;/P&gt;
&lt;P&gt;UPDATE: &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2009/06/24/it-already-is-a-scripting-language.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2009/06/24/it-already-is-a-scripting-language.aspx"&gt;More thoughts on considerations motivating this potential change here&lt;/A&gt;.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9797817" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript+.NET/default.aspx">JScript .NET</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category></item><item><title>Calling static methods on type parameters is illegal, part three</title><link>http://blogs.msdn.com/ericlippert/archive/2007/06/21/calling-static-methods-on-type-variables-is-illegal-part-three.aspx</link><pubDate>Thu, 21 Jun 2007 19:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3445650</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/3445650.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=3445650</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;There were lots of good comments on my &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/06/14/calling-static-methods-on-type-variables-is-illegal-part-one.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/06/14/calling-static-methods-on-type-variables-is-illegal-part-one.aspx"&gt;previous&lt;/A&gt; &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/06/18/calling-static-methods-on-type-variables-is-illegal-part-two.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/06/18/calling-static-methods-on-type-variables-is-illegal-part-two.aspx"&gt;entries&lt;/A&gt;&amp;nbsp;in this series. I want to address some of them, but first I want to wrap this up by considering how a small change to the scenario makes it plausible to choose a different option.&amp;nbsp; Consider now the &lt;STRONG&gt;non-static, non-virtual&lt;/STRONG&gt; instance method:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C { public void M() { /*whatever*/ } }&lt;BR&gt;public class D : C { public new void M() { /*whatever*/ } }&lt;BR&gt;public class E&amp;lt;T&amp;gt; where T : C { public static void N(T t) { t.M(); } }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;I hope you agree that in a sensibly designed language &lt;EM&gt;exactly one&lt;/EM&gt; of the following statements has to be true:&lt;/P&gt;
&lt;P&gt;1) This is illegal.&lt;BR&gt;2) &lt;SPAN class=code&gt;E&amp;lt;T&amp;gt;.N&lt;/SPAN&gt; calls &lt;SPAN class=code&gt;C.M&lt;/SPAN&gt; no matter what &lt;SPAN class=code&gt;T&lt;/SPAN&gt; is.&lt;BR&gt;3) &lt;SPAN class=code&gt;E&amp;lt;C&amp;gt;.N&lt;/SPAN&gt; calls &lt;SPAN class=code&gt;C.M&lt;/SPAN&gt; but &lt;SPAN class=code&gt;E&amp;lt;D&amp;gt;.N&lt;/SPAN&gt; calls &lt;SPAN class=code&gt;D.M&lt;/SPAN&gt; .&lt;/P&gt;
&lt;P&gt;As we've discussed, with static methods we chose the first option. But with instance methods, we choose the second! Our earlier objection to it -- that the user clearly meant for the more derived method to be called -- melts away. Why? Because as far as we are concerned, that might as well have been &lt;SPAN class=code&gt;public static void N(&lt;STRONG&gt;C&lt;/STRONG&gt; t) { t.M(); }&lt;/SPAN&gt; which you would reasonably expect to always call the less derived method, since its not virtual.&lt;/P&gt;
&lt;P&gt;Why not #3?&amp;nbsp;Again, it has to do with static analysis. What it really comes down to is that in both the static and the instance cases, &lt;SPAN class=code&gt;C.M&lt;/SPAN&gt; and &lt;SPAN class=code&gt;D.M&lt;/SPAN&gt; are &lt;STRONG&gt;entirely different methods&lt;/STRONG&gt;. The "new" calls that out; these are two different methods which just happen to share the same name. You can think of every method as having a "slot" in an object; in both the static and instance cases, we have defined two slots, not one. Had this been a virtual override then there would have been just one slot, and the &lt;EM&gt;contents&lt;/EM&gt; of that slot would be determined at runtime. But in the non-virtual case there are &lt;EM&gt;two&lt;/EM&gt; slots.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;When the compiler generates the generic code it resolves all the slots at compilation time.&lt;/STRONG&gt; &lt;STRONG&gt;The jitter does not change them&lt;/STRONG&gt;. Indeed, the jitter does not know how! The jitter has &lt;EM&gt;no idea&lt;/EM&gt; that &lt;SPAN class=code&gt;D.M&lt;/SPAN&gt; has anything to do with &lt;SPAN class=code&gt;C.M&lt;/SPAN&gt; ; again, they are completely different methods that just coincidentally share a name. They have different slots so they are different methods.&lt;/P&gt;
&lt;P&gt;I hope that all makes sense. Now to answer a few selected questions from the comments:&lt;/P&gt;
&lt;P&gt;First, a number of readers noted that there are languages (Delphi, Smalltalk) which have implemented the concept of "class" methods. That is, methods which are not associated with an instance (so they are neither instance&amp;nbsp;nor virtual), but nevertheless, which method is called is determined at runtime (so they are not static.) How the .NET versions of these languages do the codegen, I do not know; my guess would be that they emit code that does late binding via reflection or some similar mechanism.&lt;/P&gt;
&lt;P&gt;Second, this raises the question of whether C# ought to support some of the dynamic features which languages like JScript, Ruby, Python, etc, support. The VB team's motto as far as this question is concerned has always been &lt;EM&gt;early&amp;nbsp;binding when possible, late binding when necessary&lt;/EM&gt;.&amp;nbsp; The C# team, by contrast, has always cleaved to the principle that we do &lt;EM&gt;early binding when possible, late binding when the user explicitly writes umpteen dozen of lines of ugly reflection code.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;However, we do recognize both the power of dynamic language features, and the ugliness and pain of explicit reflection. We are considering ways to make late-bound code easier in C# without making it nigh-indistinguishable from early-bound code (as VB sometimes does.)&amp;nbsp; These are very preliminary thoughts; we are still finishing up C# 3.0 here; we've hardly begun thinking about C# 4.0. But when we do, dynamic language features will be high on the list of things to think about. Anyone with bright ideas, by all means, send them my way.&lt;/P&gt;
&lt;P&gt;Third, a number of readers noted that the word "static" has been consistently used in C# to mean "associated with a class", and not "determined at compile time".&amp;nbsp; I agree; this is a good example of a poorly named&amp;nbsp;abstraction. Language features should be named based on how the user is intended to use the feature, rather than on how we high-falutin' compiler designers classify different kinds of method calls. We allowed the "static" keyword to be used to mean "associated with a class". Why should "static" mean "associated with a class?"&amp;nbsp; That makes no sense at all. It's really an accident. But it is one we are stuck with now. Part of the reason why I write this blog is to dig into some of these weird historical corners and the associated unfortunate artefacts of less-than-pure design choices.&lt;/P&gt;
&lt;P&gt;And fourth, completely off topic, a reader asks us to expose the internals of the compiler's abstract syntax tree. Again, we are in the very, very early stages of designing C# 4.0, so &lt;STRONG&gt;I cannot comment on specific features or timetables&lt;/STRONG&gt;. But I will say that &lt;STRONG&gt;many people&lt;/STRONG&gt; have asked for this. I also note that in C# 2.0 and 3.0, we concentrated almost entirely on adding language features, so much so that we have fallen behind somewhat on the tools support for them.&lt;/P&gt;
&lt;P&gt;Exposing the internals of the compiler so that third parties could more easily create analysis-and-rewriting tools would be a great way to combine the power of the C# semantic analysis engine with the power of community involvement. I encourage anyone who has ideas about what sort of tools they would like to develop, and what sort of API the compiler team could provide to make that easier, to drop me a note.&amp;nbsp; We need all the real-world usage cases we can get in order to decide how to invest our time and energy in the next version.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3445650" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</category></item><item><title>Calling static methods on type parameters is illegal, part two</title><link>http://blogs.msdn.com/ericlippert/archive/2007/06/18/calling-static-methods-on-type-variables-is-illegal-part-two.aspx</link><pubDate>Mon, 18 Jun 2007 17:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3297988</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/3297988.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=3297988</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/06/14/calling-static-methods-on-type-variables-is-illegal-part-one.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/06/14/calling-static-methods-on-type-variables-is-illegal-part-one.aspx"&gt;Last time&lt;/A&gt; I pointed out that static methods are always determined exactly at compile time, and used that fact to justify why static methods cannot be called on type parameter types. But aren’t the type arguments to generics actually determined at compile time?&lt;/P&gt;
&lt;P&gt;On the caller side they are, sure. But on the callee side, the code emitted at compile time for a generic method is entirely generic. &lt;EM&gt;It is not until the jitter encounters the code at runtime that the substitution of type arguments for type parameters is done.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Consider a generic type:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C&amp;lt;T&amp;gt; { public string M() { return typeof(T).ToString(); } }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;When you compile that, the compiler emits a generic class definition which says just that – that we have a class, it has a type parameter, and a method which calls &lt;SPAN class=code&gt;ToString()&lt;/SPAN&gt;. That is &lt;EM&gt;all&lt;/EM&gt; the code which is emitted for this class at compile time.&lt;/P&gt;
&lt;P&gt;Let me make sure that is clear. When you say&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;void N() { C&amp;lt;int&amp;gt; c = new C&amp;lt;int&amp;gt;(); string s = c.M(); //...&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;the &lt;EM&gt;compiler&lt;/EM&gt; &lt;STRONG&gt;does not emit a copy of the class’s IL with &lt;SPAN class=code&gt;int&lt;/SPAN&gt; substituted for &lt;SPAN class=code&gt;T&lt;/SPAN&gt;&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;Rather, what happens is when your method &lt;SPAN class=code&gt;N&lt;/SPAN&gt; is &lt;STRONG&gt;jitted&lt;/STRONG&gt;, the jitter says hey, I need to jit up &lt;SPAN class=code&gt;C&amp;lt;int&amp;gt;.M&lt;/SPAN&gt;. At that point the jitter consumes the generic IL emitted for &lt;SPAN class=code&gt;C&amp;lt;T&amp;gt;.M&lt;/SPAN&gt; and creates brand new x86 (or whatever) code with &lt;SPAN class=code&gt;int&lt;/SPAN&gt; substituted for &lt;SPAN class=code&gt;T&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;Contrast this with C++ templates. C++ templates do not define generic types. Rather, C++ templates are basically a clever compile-time syntax for some complex search-and-replace macros. If you say &lt;SPAN class=code&gt;C&amp;lt;int&amp;gt;&lt;/SPAN&gt; in C++, then at compile time the C++ compiler textually substitutes &lt;SPAN class=code&gt;int&lt;/SPAN&gt; for &lt;SPAN class=code&gt;T&lt;/SPAN&gt; and emits code &lt;EM&gt;as if that was how you had written it in the first place.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;If C# had templates instead of macros then a static method called on a template parameter really &lt;EM&gt;would&lt;/EM&gt; be determined at compile time, because the entire constructed class would be resolved at compile time. In this sense templates are a more powerful mechanism than generics – you can do crazy things with templates because &lt;EM&gt;there is no type safety imposed upon the template as a whole&lt;/EM&gt;. Rather, the type safety is only checked for &lt;EM&gt;every construction of the template actually in the program&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;But C# generic types are not templates; &lt;EM&gt;they must be typesafe given any possible construction which satisfies the constraints&lt;/EM&gt;, not just under the set that they are actually constructed from in a particular program.&lt;/P&gt;
&lt;P&gt;Next time I'll consider what impact these design decisions have on non-virtual instance methods called from within generic types.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3297988" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</category></item><item><title>Calling static methods on type parameters is illegal, part one</title><link>http://blogs.msdn.com/ericlippert/archive/2007/06/14/calling-static-methods-on-type-variables-is-illegal-part-one.aspx</link><pubDate>Thu, 14 Jun 2007 23:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3297159</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>25</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/3297159.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=3297159</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;A developer passed along&amp;nbsp;a question from a customer to our internal mailing list for C# questions the other day.&amp;nbsp;Consider the following:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C { public static void M() { /*whatever*/ } }&lt;BR&gt;public&amp;nbsp;class&amp;nbsp;D : C { public new static void M() { /*whatever*/ } }&lt;BR&gt;public class E&amp;lt;T&amp;gt; where T : C { public static void N() { T.M(); } }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;That's illegal. We do not allow you to call a static method on a type parameter. The question is, why? We know that &lt;SPAN class=code&gt;T&lt;/SPAN&gt; must be a &lt;SPAN class=code&gt;C&lt;/SPAN&gt;, and &lt;SPAN class=code&gt;C&lt;/SPAN&gt; has a static method &lt;SPAN class=code&gt;M&lt;/SPAN&gt;, so why shouldn't this be legal?&lt;/P&gt;
&lt;P&gt;I hope you agree that in a sensibly designed language &lt;EM&gt;exactly one&lt;/EM&gt; of the following statements has to be true:&lt;/P&gt;
&lt;P&gt;1) This is illegal.&lt;BR&gt;2) &lt;SPAN class=code&gt;E&amp;lt;T&amp;gt;.N()&lt;/SPAN&gt; calls &lt;SPAN class=code&gt;C.M()&lt;/SPAN&gt; no matter what &lt;SPAN class=code&gt;T&lt;/SPAN&gt; is.&lt;BR&gt;3) &lt;SPAN class=code&gt;E&amp;lt;C&amp;gt;.N()&lt;/SPAN&gt; calls &lt;SPAN class=code&gt;C.M()&lt;/SPAN&gt; but &lt;SPAN class=code&gt;E&amp;lt;D&amp;gt;.N()&lt;/SPAN&gt; calls &lt;SPAN class=code&gt;D.M()&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;(If there is a fourth possible sensible behaviour which I have missed, I am happy to consider its merits.)&lt;/P&gt;
&lt;P&gt;If we pick (2) then this is both potentially misleading and totally pointless. The user will reasonably expect &lt;SPAN class=code&gt;D.M()&lt;/SPAN&gt; to be called if &lt;SPAN class=code&gt;T&lt;/SPAN&gt; is a &lt;SPAN class=code&gt;D&lt;/SPAN&gt;. Why else would they go to the trouble of saying &lt;SPAN class=code&gt;T.M()&lt;/SPAN&gt; instead of &lt;SPAN class=code&gt;C.M()&lt;/SPAN&gt; if they mean "always call &lt;SPAN class=code&gt;C.M()&lt;/SPAN&gt;"? &lt;/P&gt;
&lt;P&gt;If we pick (3) then we have violated the core design principle of static methods, the principle that gives them their name. Static methods are called “static” because &lt;EM&gt;it can always be determined exactly, at compile time, what method will be called&lt;/EM&gt;. That is, the method can be resolved solely by &lt;EM&gt;static analysis&lt;/EM&gt; of the code.&lt;/P&gt;
&lt;P&gt;That leaves (1).&lt;/P&gt;
&lt;P&gt;Related questions come up frequently, in various forms. Usually people phrase it by asking me why C# does not support “virtual static” methods. I am always at a loss to understand what they could possibly mean, since “virtual” and “static” are opposites! “virtual” means “determine the method to be called based on run time type information”, and “static” means “determine the method to be called solely based on compile time static analysis”. &lt;/P&gt;
&lt;P&gt;(Then again, people occasionally accuse me of “dogmatic skepticism”. Since “dogmatic” and “skeptical” are opposites, I am never sure quite what they mean either. My conclusion: people sometimes say strange things.)&lt;/P&gt;
&lt;P&gt;Really what people want I think is yet another kind of method, which would be none of static, instance or virtual. We could come up with a kind of method which behaved like our option (3) above. That is, a method associated with a type (like a static), which does not take a non-nullable “this” argument (unlike an instance or virtual), but one where the method called would depend on the constructed type of &lt;SPAN class=code&gt;T&lt;/SPAN&gt; (unlike a static, which must be determinable at compile time). &lt;/P&gt;
&lt;P&gt;I’m not sure whether the CLR generic system supports codegenning such a beast, but other than that, I don’t see any in-principle reason why such a thing would be difficult to do. But we do not add language features just because we can; we add them when the compelling benefit outweighs the costs. No one has yet made the case to me that this kind of method would be really useful. &lt;/P&gt;
&lt;P&gt;Next time I'll answer the follow-up question: why&lt;EM&gt; isn't&lt;/EM&gt; this determined at compile time? That will take us into the subtle differences between &lt;EM&gt;templates&lt;/EM&gt; and &lt;EM&gt;generic types&lt;/EM&gt;. They are often confused.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3297159" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</category></item><item><title>Why are overloaded operators always static in C#?</title><link>http://blogs.msdn.com/ericlippert/archive/2007/05/14/why-are-overloaded-operators-always-static-in-c.aspx</link><pubDate>Tue, 15 May 2007 00:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2634343</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/2634343.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=2634343</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;A language design question was posted to the Microsoft internal C# discussion group this morning: "&lt;EM&gt;Why must overloaded operators be static in C#? In C++ an overloaded operator can be implemented by a static, instance or virtual method. Is there some reason for this constraint in C#?&lt;/EM&gt;"&lt;/P&gt;
&lt;P&gt;Before I get into the specifics, there is a larger point here worth delving into, or at least linking to. &lt;A class="" href="http://blogs.msdn.com/oldnewthing/" mce_href="http://blogs.msdn.com/oldnewthing/"&gt;Raymond Chen&lt;/A&gt; immediately pointed out that the questioner had it backwards. The design of the C# language is not a &lt;STRONG&gt;subtractive&lt;/STRONG&gt; process; though I take &lt;A class="" href="http://www.pbs.org/cringely/pulpit/2001/pulpit_20011101_000710.html" mce_href="http://www.pbs.org/cringely/pulpit/2001/pulpit_20011101_000710.html"&gt;Bob Cringely's rather backhanded compliments&lt;/A&gt; from 2001 in the best possible way, C# is &lt;STRONG&gt;not&lt;/STRONG&gt; Java/C++/whatever with the kludgy parts removed. Former C# team member Eric Gunnerson wrote &lt;A class="" href="http://blogs.msdn.com/ericgu/archive/2004/01/12/57985.aspx" mce_href="http://blogs.msdn.com/ericgu/archive/2004/01/12/57985.aspx"&gt;a great article about how the process actually works&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Rather, the question we should be asking ourselves when faced with a potential language feature is "does the compelling benefit of the feature justify all the costs?" And costs are considerably more than just the mundane dollar costs of designing, developing, testing, documenting and maintaining a feature. There are more subtle costs, like, will this feature make it more difficult to change the type inferencing algorithm in the future? Does this lead us into a world where we will be unable to make changes without introducing backwards compatibility breaks? And so on.&lt;/P&gt;
&lt;P&gt;In this specific case, the compelling benefit is small. If you want to have a virtual dispatched overloaded operator in C# you can build one out of static parts very easily. For example:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class B {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static B operator+(B b1, B b2) { return b1.Add(b2); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected virtual B Add(B b2) { // ...&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;And there you have it. So, the benefits are small. But the costs are large. C++-style instance operators are weird. For example, they break symmetry. If you define an &lt;SPAN class=code&gt;operator+&lt;/SPAN&gt; that takes a &lt;SPAN class=code&gt;C&lt;/SPAN&gt; and an &lt;SPAN class=code&gt;int&lt;/SPAN&gt;, then &lt;SPAN class=code&gt;c+2&lt;/SPAN&gt; is legal but &lt;SPAN class=code&gt;2+c&lt;/SPAN&gt; is not, and that badly breaks our intuition about how the addition operator should behave.&lt;/P&gt;
&lt;P&gt;Similarly, with virtual operators in C++, the left-hand argument is the thing which parameterizes the virtual dispatch. So again, we get this weird asymmetry between the right and left sides. Really what you want for most binary operators is double dispatch -- you want the operator to be virtualized on the types of both arguments, not just the left-hand one. But neither C# nor C++ supports double dispatch natively. (Many real-world problems would be solved if we had double dispatch; for one thing, &lt;A class="" href="http://blogs.msdn.com/devdev/archive/2005/08/29/457798.aspx" mce_href="http://blogs.msdn.com/devdev/archive/2005/08/29/457798.aspx"&gt;the visitor pattern becomes trivial&lt;/A&gt;. My colleague &lt;A class="" href="http://blogs.msdn.com/wesdyer/" mce_href="http://blogs.msdn.com/wesdyer/"&gt;Wes&lt;/A&gt; is fond of pointing out that most design patterns are in fact necessary only insofar as the language has failed to provide a needed feature natively.)&lt;/P&gt;
&lt;P mce_keep="true"&gt;And finally, in C++ you can only define an overloaded operator on a non-pointer type. This means that when you see &lt;SPAN class=code&gt;c+2&lt;/SPAN&gt; and rewrite it as &lt;SPAN class=code&gt;c.operator+(2)&lt;/SPAN&gt;, you are guaranteed that &lt;SPAN class=code&gt;c&lt;/SPAN&gt; is not a null pointer because it is not a pointer! C# also makes a distinction between values and references, but it would be very strange if instance operator overloads were only definable on non-nullable value types, and it would also be strange if &lt;SPAN class=code&gt;c+2&lt;/SPAN&gt; could throw a null reference exception.&lt;/P&gt;
&lt;P mce_keep="true"&gt;These and other difficulties along with the ease of building your own single (or double!) virtual dispatch mechanisms out of static mechanisms, makes it easy to decide to not add instance or virtual operator overloading to C#.&lt;/P&gt;&lt;/DIV&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2634343" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</category></item></channel></rss>