<?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 : JScript .NET</title><link>http://blogs.msdn.com/ericlippert/archive/tags/JScript+.NET/default.aspx</link><description>Tags: JScript .NET</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><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>C# 3.0 is still statically typed, honest!</title><link>http://blogs.msdn.com/ericlippert/archive/2005/09/27/c-3-0-is-still-statically-typed-honest.aspx</link><pubDate>Tue, 27 Sep 2005 20:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474462</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>23</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/474462.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=474462</wfw:commentRss><description>&lt;FONT face="lucida sans unicode"&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;Since LINQ was announced I've seen a lot of really positive feedback and a lot of questions and concerns. Keep 'em coming! We need this feedback so that we can both correct misconceptions early and get the design right now.&lt;/P&gt;
&lt;P&gt;One of the misconceptions that I've seen a lot over the last few days in forums, blog posts and private emails is a confusion about what the new "type inferencing" feature implies for the type safety of the language. Apparently we have not been sufficiently clear on this point: &lt;B&gt;C# 3.0 will be statically typed, just like&amp;nbsp;C# 1.0 and 2.0. The var declaration style does not introduce dynamic typing or duck typing to C#.&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;I think the confusion may arise from familiarity with other languages such as JScript. In JScript this is perfectly legal:&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;var foo = new Blah();&lt;BR&gt;foo = 123;&lt;BR&gt;foo = "hello";&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;JScript is a dynamically typed language. You can assign any value of any type to a var.&lt;/P&gt;
&lt;P&gt;In C# 3.0, the var statement&amp;nbsp;means&amp;nbsp;"look at the type of the thing assigned to the variable, and act as though the variable was declared with that type." In other words, in C# the code above is just a syntactic sugar for&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;&lt;STRONG&gt;Blah&lt;/STRONG&gt; foo = new Blah();&lt;BR&gt;foo = 123;&lt;BR&gt;foo = "hello";&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;which of course would produce a type error on the second and third lines.&lt;/P&gt;
&lt;P&gt;If you take a look at section 26.1 of the C# 3.0 specification you'll see that the var statement has a lot of restrictions on it to ensure that the compiler always has enough information to make the correct type inference. Namely:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;the declarator must include an initializer, so that we can infer the type of the variable from the type of the initializer&lt;/LI&gt;
&lt;LI&gt;the initializer has to be something that we can figure out the type of – not null or a collection initializer&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Compare this to JScript .NET, which has a much stronger type inference mechanism. JScript .NET does not require initializers in var statements; the compiler tracks all assignments to the variable and infers the best type. If, say, only strings are assigned to a variable then it will infer the string type. JScript .NET also infers return types of functions by a similar mechanism. But the goal of the JScript .NET type inference mechanism was to &lt;STRONG&gt;increase the performance of legacy dynamically typed code&lt;/STRONG&gt;. If we can infer a type and thereby generate faster, smaller code, we do so.&amp;nbsp; If not, we don't.&lt;/P&gt;
&lt;P&gt;Then why introduce this syntactic sugar in C# 3.0? C# doesn't have a body of legacy dynamic code like JScript and already generates efficient code.&lt;/P&gt;
&lt;P&gt;There are two reasons, one which exists today, one which will crop up in 3.0. &lt;/P&gt;
&lt;P&gt;The first reason is that this code is incredibly ugly because of all the redundancy:&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt; mylists = new Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt;();&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;And that's a simple example – I've written worse. Any time you're forced to type exactly the same thing twice, that's a redundancy that we can remove. Much nicer to write&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;var mylists = new Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt;();&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;and let the compiler figure out what the type is based on the assignment.&lt;/P&gt;
&lt;P&gt;Second, C# 3.0 introduces anonymous types. Since anonymous types by definition have no names, you need to be able to infer the type of the variable from the initializing expression if its type is anonymous.&lt;/P&gt;
&lt;P&gt;We'll discuss the reasoning behind anonymous types in another post.&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=474462" 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/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx">Type Inference</category></item><item><title>Instance-bound nested classes in JScript .NET</title><link>http://blogs.msdn.com/ericlippert/archive/2005/05/02/414015.aspx</link><pubDate>Mon, 02 May 2005 21:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:414015</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/414015.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=414015</wfw:commentRss><description>&lt;FONT face="lucida sans unicode"&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;The other day someone asked me about a slightly odd but very useful feature in JScript.NET,&amp;nbsp;and I figure if one person asks me about it, maybe more people want to know as well.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In JScript.NET you can say&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;class alpha {&lt;BR&gt;&amp;nbsp; var foo;&lt;BR&gt;&amp;nbsp; class bravo {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function blah() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print (foo);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;var x = new alpha();&lt;BR&gt;x.foo = 123;&lt;BR&gt;var z = new x.bravo();&lt;BR&gt;z.blah();&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;the instance of alpha is bound to the &lt;I&gt;instance&lt;/I&gt; of bravo's scope chain. Therefore when z.blah runs, foo is bound to x.foo. Of course, this means that when you instantiate a new instance of the inner class, you've got to do so via an instance of the enclosing class.&lt;/P&gt;
&lt;P&gt;We implemented this in JScript .NET so that ASP.NET would work nicely. Behind the scenes, ASP.NET builds a class which extends a page class and sticks your code into it. If you had something like&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&amp;lt;script runat="server"&amp;gt;&lt;BR&gt;&amp;nbsp; class foo {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function bar() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write("hello");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;}&lt;BR&gt;&amp;lt;/script&amp;gt;&lt;BR&gt;&amp;lt;%&lt;BR&gt;&amp;nbsp; var x = new foo();&lt;BR&gt;&amp;nbsp; foo.bar();&lt;BR&gt;%&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;Then that would generate a class roughly like this:&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;&lt;BR&gt;class MyPage extends Page {&lt;BR&gt;&amp;nbsp; class foo {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function bar() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write("hello");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; function Render() {&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var x = new foo();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foo.bar();&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;The nested class is bound to the page instance, and hence can access the Response object of the page base class. The JScript.NET compiler is smart enough to figure out that really you meant&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var x = new this.foo();&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;C# does not implement instance-bound nested classes. If you want C#-like behaviour in JScript.NET, you can get it. In JScript.NET if you don't want a nested class to be bound to an instance of the outer class then you stick the &lt;FONT color=#000080&gt;static&lt;/FONT&gt; modifier onto the inner class declaration. In that case, the enclosing class essentially becomes not much more than another level of namespace.&lt;/P&gt;
&lt;P&gt;Would you like to see something like this in a hypothetical future version of C#? Would it be useful? &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=414015" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript+.NET/default.aspx">JScript .NET</category></item><item><title>Fun With Floating Point Arithmetic, Part Six</title><link>http://blogs.msdn.com/ericlippert/archive/2005/01/26/fun-with-floating-point-arithmetic-part-six.aspx</link><pubDate>Wed, 26 Jan 2005 21:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:361041</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/361041.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=361041</wfw:commentRss><description>&lt;font face="Lucida Sans Unicode"&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;One more thing -- I said earlier that the VBScript float-to-string algorithm was a little bit different than the JScript algorithm. We can demonstrate quite easily by comparing the outputs of two nigh-identical programs:&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#333399" size="2"&gt; &lt;p&gt;' VBScript&lt;br /&gt;print 9.2 * 100.0 &amp;lt; 920.0&lt;br /&gt;print 919.9999999999999 &amp;lt; 920.0 &lt;br /&gt;print 920.0000000000001 &amp;gt; 920.0&lt;/p&gt; &lt;p&gt;' JScript&lt;br /&gt;print(9.2*100.00 &amp;lt; 920.0);&lt;br /&gt;print(919.9999999999999 &amp;lt; 920.0);&lt;br /&gt;print (920.0000000000001 &amp;gt; 920.0);&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;As you'd expect, the last two comparisons of each result in true. But why does the first also result in true? Because of the very issues we've been talking about in the last five parts -- 9.2 cannot be exactly represented as a float. There is some representation error. When the float is multiplied by 100, the representation error also gets 100 times larger, and that's big enough to make it slightly smaller than 920.&lt;/p&gt; &lt;p&gt;If that's the case then why do these programs produce different output?&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#333399" size="2"&gt; &lt;p&gt;print 9.2 * 100.0&lt;br /&gt;print 919.9999999999999 &lt;br /&gt;print 920.0000000000001&lt;/p&gt; &lt;p&gt;print(9.2*100.00);&lt;br /&gt;print(919.9999999999999);&lt;br /&gt;print(920.0000000000001);&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;The VBScript program produces 920, 920, 920. The JScript program produces 919.9999999999999, 919.9999999999999, 920.0000000000001. What is up with that?&lt;/p&gt; &lt;p&gt;The JScript algorithm for converting floats to strings is designed to have as much precision as possible. Since 919.9999999999999 and 920.0 have different binary representations as floats, they have different string representation. &lt;/p&gt; &lt;p&gt;The VBScript algorithm on the other hand assumes that if you have 919.9999999999999 or 920.0000000000001, that probably what has happened is you've run into a floating point error accrual&amp;nbsp;issue, and it rounds it back to the correct value for you when it displays the string. &lt;/p&gt; &lt;p&gt;This heuristic means that VBScript (paradoxically) loses a small amount of precision and yet displays more accurate results for typical cases. The down side is that VBScript is unable to display full&amp;nbsp;precision when you really DO want to represent 919.9999999999999. Such cases are quite rare though, and the error created in such cases is tiny.&lt;/p&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=361041" 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/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Floating+Point+Arithmetic/default.aspx">Floating Point Arithmetic</category></item><item><title>Fun with Floating Point Arithmetic, Part Five</title><link>http://blogs.msdn.com/ericlippert/archive/2005/01/20/fun-with-floating-point-arithmetic-part-five.aspx</link><pubDate>Thu, 20 Jan 2005 18:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:357407</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/357407.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=357407</wfw:commentRss><description>&lt;font face="lucida sans unicode"&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;I went to &lt;a href="http://www.joelonsoftware.com"&gt;Joel Spolsky's &lt;/a&gt;geek dinner at Crossroads the other night, which was a lot of fun. I didn't get much of a chance to chat with Joel, as he was surrounded by a cadre of adoring fans three deep the whole time.&amp;nbsp; I mostly hung out with &lt;A href="http://blogs.msdn.com/kclemson/"&gt;KC &lt;/a&gt;and &lt;A href="http://blogs.msdn.com/larryosterman/"&gt;Larry &lt;/a&gt;and some other attendees and had an interesting talk about digital rights management, corporate blogging, and the difficulties of finding good quality Jackie Chan movies in the original Chinese.&lt;/p&gt; &lt;p&gt;I ran into &lt;a href="http://wesnerm.blogs.com/net_undocumented/"&gt;Wesner Moise&lt;/a&gt;, who I first met long ago when he was working on Access or Excel or one of those Office kind of products but haven't really run into since.&amp;nbsp;He was rather surprised that I remembered his name, but hey, how many Wesner Moises do you think I meet?&amp;nbsp; &lt;/p&gt; &lt;p&gt;Anyway, coincidentally, Wesner has also been running a series on the perils of floating point and integer mathematics&amp;nbsp;on his blog recently.&amp;nbsp;Check it out!&amp;nbsp; &lt;/p&gt; &lt;p&gt;*********************************&lt;/p&gt; &lt;p&gt;I said a while back that floating point math is nothing like the math we're used to.&amp;nbsp;Consider some of the properties that define real number addition. For instance:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;closure&lt;/strong&gt;: x + y is a number&lt;br /&gt;&lt;strong&gt;commutative&lt;/strong&gt;: x + y = y + x&lt;br /&gt;&lt;strong&gt;unique zero&lt;/strong&gt;: a + b = a&amp;nbsp;if and only if&amp;nbsp;b&amp;nbsp;= 0&lt;br /&gt;&lt;strong&gt;associative&lt;/strong&gt;: (x + y ) + z = x + (y + z)&lt;/p&gt; &lt;p&gt;and so on, and similarly for multiplication. Commutivity still holds, but many of these rules do not work in floating point arithmetic.&amp;nbsp; I'll dig into a few of them here -- for more math rules that don't work in floating point, see Wesner's blog articles on the subject.&amp;nbsp; He lists dozens of them!&lt;/p&gt; &lt;p&gt;Consider the closure property, for example. It's not true in VBScript:&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;print 10^308 + 10^308 ' Overflow error&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;It is true in JScript, if you consider Infinity to be a number.&lt;/p&gt; &lt;p&gt;The commutative property is true in both VBScript and JScript, but the unique zero, and hence the associative property, are true in neither: &lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;print 10^20&amp;nbsp;= 10^20 + 5000 &lt;/font&gt;&lt;font color="#800080" size="2"&gt;prints &lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;True -- &lt;/font&gt;&lt;font color="#800080" size="2"&gt;So clearly, zero is not a unique number which, when added, results in the same value. (Zero is unique in that it is the only number when added to EVERY number, results in no change. But almost every number has multiple values which result in no change when added.)&lt;/p&gt; &lt;p&gt;That means that the associative property goes out the window: &lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;print 10^20 + (5000 + 5000) = (10^20 + 5000) + 5000 &lt;/font&gt;&lt;font color="#800080" size="2"&gt;prints &lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;False&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;The fact that the order in which you make the additions can affect the result makes a difference if you are designing algorithms that must add up lots of little things to one big thing. In those cases, &lt;strong&gt;you should try to add together all the little things first, and then add the total to the big thing.&lt;/strong&gt; That way, the small additions are done with the most precision possible.&lt;/p&gt; &lt;p&gt;There's a related error due to rounding off. 1/100 cannot be represented perfectly accurately in binary any more than 1/3 can be represented perfectly in decimal:&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;var steps = 100;&lt;br /&gt;var start = 10;&lt;br /&gt;var stop = 11;&lt;br /&gt;var current = start;&lt;br /&gt;do&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; print(current);&lt;br /&gt;&amp;nbsp; current = current + (stop-start)/steps;&lt;br /&gt;} while (current &amp;lt; stop)&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;Which ends up with&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;...&lt;br /&gt;10.96999999999998&lt;br /&gt;10.979999999999979&lt;br /&gt;10.989999999999979&lt;br /&gt;10.999999999999978&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;This actually takes 101 steps, because the last one through the loop gets to 10.999999999999978, which is less than 11.0. &amp;nbsp;This tiny accumulated error results in the algorithm running for 1% too many steps. A better algorithm is to do the looping in integers and compute the current value anew every time:&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;var steps = 100;&lt;br /&gt;var start = 10;&lt;br /&gt;var current;&lt;br /&gt;for (var step = 0; step &amp;lt; steps ; ++step)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; current = start + step/steps;&lt;br /&gt;&amp;nbsp; print(current);&lt;br /&gt;}&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080"&gt; &lt;p&gt;&lt;font size="2"&gt;That actually runs the right number of steps.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;A corollary of this is that you should almost never compare two floating point numbers for equality, because you never know when some rounding error might have crept in. Rather, subtract them and look at the absolute difference.&amp;nbsp; For instance, if you know that x and y are positive floats that are likely to be close to each other, don't say&amp;nbsp;&lt;font face="Lucida Console" color="#000080"&gt;if (x==y)&lt;/font&gt;&lt;font size="3"&gt;, say &lt;/font&gt;&lt;font color="#800080"&gt;&lt;font face="Lucida Console" color="#000080"&gt;if (Math.abs(x-y) &amp;lt; 0.0001)&lt;font face="Lucida Sans Unicode" color="#800080"&gt; or &lt;/font&gt;&lt;font color="#800080"&gt;&lt;font face="Lucida Console" color="#000080"&gt;if (Math.abs(x-y) &amp;lt; 0.0000001 * x) &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#800080"&gt;&lt;font size="2"&gt;or whatever makes sense in your application.&amp;nbsp; (If you need to deal with NaNs and infinities, simple subtraction is anything but!)&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;We saw above that addition of a small number to a large number can lead to an erroneous result, but the error was extremely small.&amp;nbsp; An error of 5000 in a number as big as 10&lt;sup&gt;20&lt;/sup&gt; is 0.00000000000002%, which ain't bad.&amp;nbsp;&amp;nbsp;W&lt;/font&gt;&lt;font size="2"&gt;e'd expect that subtraction of two numbers very close to each other would also produce an erroneous result, but with a similar error percentage.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;We'd be wrong. H&lt;/font&gt;&lt;font size="2"&gt;ere's an example:&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;Suppose you have to solve an arbitrary quadratic equation:&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;A x&lt;sup&gt;2&lt;/sup&gt; + B x + C = 0&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;The solutions are well known, so we can write a little subroutine:&lt;/font&gt;&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080"&gt; &lt;p&gt;&lt;font size="2"&gt;Sub SolveQuadratic(A, B, C)&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Discriminant = B*B-4*A*C&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;If Discriminant &amp;lt; 0 Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Print "No real solutions"&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Print (-B + Sqr(Discriminant)) / (2 * A)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Print (-B - Sqr(Discriminant)) / (2 * A)&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;End If&lt;br /&gt;&lt;/font&gt;&lt;font size="2"&gt;End Sub&lt;br /&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt;SolveQuadratic 2, 5, -12&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;And sure enough, it prints out -4 and 1.5, done. What about&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080" size="2"&gt; &lt;p&gt;SolveQuadratic 1, -10000000.0000001, 1&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080"&gt; &lt;p&gt;&lt;font size="2"&gt;The correct solutions are 10000000 and 0.0000001, but this prints out 10000000 and 9.96515154838562E-08, yielding an error of nearly 3.5%! We've got about &lt;strong&gt;a&amp;nbsp;hundred&amp;nbsp;trillion times as much error&lt;/strong&gt; here as we did in the addition. &lt;/font&gt;&lt;font size="2"&gt;Why? &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;Because B and the root of the discriminant are &lt;em&gt;very, very&lt;/em&gt; close to each other.&amp;nbsp; You only get 15 decimal places of accuracy, and we've used them all up.&amp;nbsp;Therefore, the difference is going to be&amp;nbsp;&lt;em&gt;very&lt;/em&gt; inaccurate. Their sum, however, is going to be quite accurate, since they're of similar size and precision.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;Fortunately, in this example there's a trick. The product of the two solutions is always C / A, so we can use this fact to write a better algorithm:&lt;/font&gt;&lt;/p&gt;&lt;/font&gt;&lt;font face="Lucida Console" color="#000080"&gt; &lt;p&gt;&lt;font size="2"&gt;Sub SolveQuadratic(A, B, C)&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Discriminant = B*B-4*A*C&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;If Discriminant &amp;lt; 0 Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Print "No real solutions"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Exit Sub&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;End If&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Soln1 = (-B - Sqr(Discriminant)) / (2 * A)&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Soln2 = (-B + Sqr(Discriminant)) / (2 * A)&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;If Abs(Soln1) &amp;lt; Abs(Soln2) Then Soln1 = Soln2&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Soln2 = C / (A * Soln1)&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Print Soln1&lt;br /&gt;&amp;nbsp; &lt;/font&gt;&lt;font size="2"&gt;Print Soln2&lt;br /&gt;&lt;/font&gt;&lt;font size="2"&gt;End Sub&lt;/font&gt;&lt;/p&gt;&lt;/font&gt;&lt;font color="#800080" size="2"&gt; &lt;p&gt;Which produces a much more accurate result. &lt;/p&gt; &lt;p&gt;But wait a minute -- addition is order-dependent, as we've seen.&amp;nbsp;so&amp;nbsp;are multiplication and division. Should that be &lt;font color="#000080"&gt;( C / A ) / Soln1&lt;/font&gt; or &lt;font color="#000080"&gt;C / (A * Soln1)&lt;/font&gt; ? Or does it even matter? Figuring that out&amp;nbsp;is left as an exercise for the reader!&lt;/p&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=357407" 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/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Floating+Point+Arithmetic/default.aspx">Floating Point Arithmetic</category></item><item><title>JScript .NET Type Coercion Semantics, Part Four: Coercion at last</title><link>http://blogs.msdn.com/ericlippert/archive/2004/08/10/212080.aspx</link><pubDate>Tue, 10 Aug 2004 17:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:212080</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/212080.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=212080</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Before I get going, a couple notable milestones.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;First, this is &lt;STRONG&gt;post number 200&lt;/STRONG&gt;!&amp;nbsp; Who would have believed that I'd have so much to ramble on about?&amp;nbsp; ("Anyone who knows you" would be the correct answer to that rhetorical question I suppose.)&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Second, as of Sunday I am now over (cue Dr. Evil) &lt;B&gt;&lt;SPAN&gt;one billion seconds&lt;/SPAN&gt;&lt;/B&gt; old.&amp;nbsp; Happy gigasecond to me, happy gigasecond to me&amp;#8230;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;OK, enough frivolity.&amp;nbsp; Back to boring facts about JScript .NET's coercibility algorithm.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;**************************
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Today I'll finish up and give a more precise definition of how JScript .NET determines whether a particular value is coercible to a given type. Then we'll get back into lighter topics.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suppose we have a value V which we wish to coerce to type T &lt;B&gt;&lt;SPAN&gt;without data loss or error&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; For clarity I'll split the algorithm up into two sections, one for "special" types like classes, arrays and enumerations, and one for "primitive value" types like integers and strings.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suppose T is a reference, enumerated, array, etc, type:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If V is &lt;B&gt;&lt;SPAN&gt;null or undefined&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T irrespective of T.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is &lt;B&gt;&lt;SPAN&gt;System.Object&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T irrespective of V.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;class&lt;/SPAN&gt;&lt;/B&gt; and V is an &lt;B&gt;&lt;SPAN&gt;instance&lt;/SPAN&gt;&lt;/B&gt; of T (which includes being an instance of a subclass of T) then V is coercible to T.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is an &lt;B&gt;&lt;SPAN&gt;interface&lt;/SPAN&gt;&lt;/B&gt; and V &lt;B&gt;&lt;SPAN&gt;implements&lt;/SPAN&gt;&lt;/B&gt; T then V is coercible to T.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;non-JScript array of known element type E&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; every element of V is coercible to E.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;rank-one non-JScript array&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is an &lt;B&gt;&lt;SPAN&gt;enumerated type&lt;/SPAN&gt;&lt;/B&gt; and &amp;nbsp;V is a &lt;B&gt;&lt;SPAN&gt;member of enumerated type E&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; T and E are the same type.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is an &lt;B&gt;&lt;SPAN&gt;enumerated type&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; and then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; V names a member of T.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is an &lt;B&gt;&lt;SPAN&gt;enumerated type of implementation type E&lt;/SPAN&gt;&lt;/B&gt; and V is &lt;B&gt;&lt;SPAN&gt;not a member of an enumerated type&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; V is coercible to E.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is the &lt;B&gt;&lt;SPAN&gt;System.Type&lt;/SPAN&gt;&lt;/B&gt; type and V is a &lt;B&gt;&lt;SPAN&gt;class name&lt;/SPAN&gt;&lt;/B&gt; (not an &lt;I&gt;&lt;SPAN&gt;instance&lt;/SPAN&gt;&lt;/I&gt; of a class but actually the name of a class) then V is coercible to T.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;delegate type&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;function object&lt;/SPAN&gt;&lt;/B&gt; (including a closure) then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; V has the same function signature as the delegate.&lt;/LI&gt;
&lt;LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T &lt;B&gt;&lt;SPAN&gt;defines an appropriate type coercion function&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; the function call doesn't throw an exception.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now let's consider the primitive type coercion rules.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;JScript .NET supports several numeric types: 8, 16, 32 and 64 bit integers in both signed and unsigned flavours, 32 and 64 bit floats and a decimal type.&amp;nbsp; JScript .NET also supports a "char" type which is an unsigned 16 bit integer that holds a single Unicode UTF-16 value.&amp;nbsp; JScript .NET also supports a scalar Date/Time type which is treated the same as a signed 64 bit integer unless otherwise noted.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Note that &lt;B&gt;&lt;SPAN&gt;data loss is allowed when coercing anything to Boolean and when coercing strings to numbers.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T &lt;B&gt;&lt;SPAN&gt;is the type&lt;/SPAN&gt;&lt;/B&gt; of V then V is coercible to T.&amp;nbsp; (Duh!)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If V is &lt;B&gt;&lt;SPAN&gt;undefined or null&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T irrespective of T.&amp;nbsp; (FYI, coercing V to Boolean goes to false.&amp;nbsp; Coercing V to any numeric type goes to 0. Coercing V to string goes to "".)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If V is &lt;B&gt;&lt;SPAN&gt;Boolean&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T irrespective of T.&amp;nbsp; (FYI, coercing a V to a numeric type goes to 0 or 1, coercing V to string goes to "true" or "false".)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If V is &lt;B&gt;&lt;SPAN&gt;char&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T irrespective of T. (FYI, coercing V to Boolean goes to false if char is \u0000, true otherwise.&amp;nbsp; Coercing V to numeric goes to the UTF-16 value. Coercing V to string goes to a single-character string.)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is &lt;B&gt;&lt;SPAN&gt;any numeric type&lt;/SPAN&gt;&lt;/B&gt; and V is a member of &lt;B&gt;&lt;SPAN&gt;any numeric type&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T if and only if V can be coerced to T without overflow or loss of precision.&amp;nbsp; For instance, if V were the unsigned 8-byte integer 300 then V could be coerced to an unsigned 2-byte integer regardless of the fact that the 8-byte unsigned integer type is not promotable to the 2 byte integer type. Note that if V is, say, the 8-byte float value 0.1 then this is not coercible to a 4-byte float as there will be a loss of precision.&amp;nbsp; (0.5 would be coercible.)&amp;nbsp; Recall that the assignability algorithm has a special case to ensure that compile-time constants inferred to be 64 bit floats are assignable to 32 bit floats even if they are not coercible.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; and V is of &lt;B&gt;&lt;SPAN&gt;any numeric type&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T.&amp;nbsp; (JScript .NET uses the standard number-to-string routine.&amp;nbsp; If V is a Date/Time scalar then it uses the appropriate date string.)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is &lt;B&gt;&lt;SPAN&gt;Boolean&lt;/SPAN&gt;&lt;/B&gt; and V is of &lt;B&gt;&lt;SPAN&gt;any numeric type&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T.&amp;nbsp; (If V is zero or NaN then it goes to false, otherwise it goes to true.)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is &lt;B&gt;&lt;SPAN&gt;Boolean&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T.&amp;nbsp; (If V is "" then it goes to false, otherwise true.)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;date type&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; V is parsable as a date.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is &lt;B&gt;&lt;SPAN&gt;char&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; V is a &lt;B&gt;&lt;SPAN&gt;single-character string.&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;numeric type&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; &lt;B&gt;&lt;SPAN&gt;that can be parsed as type T&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If T is a &lt;B&gt;&lt;SPAN&gt;numeric type&lt;/SPAN&gt;&lt;/B&gt; and V is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; &lt;B&gt;&lt;SPAN&gt;that cannot be parsed as type T&lt;/SPAN&gt;&lt;/B&gt; then V is coercible to T &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; V is parsable to an 8-byte float and the resulting float value is coercible to T.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If none of the above apply, V is not coercible to T, and will likely cause a type mismatch exception.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=212080" 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></item><item><title>JScript .NET Type Coercion Semantics, Part Three: Assignability </title><link>http://blogs.msdn.com/ericlippert/archive/2004/08/06/209991.aspx</link><pubDate>Fri, 06 Aug 2004 17:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:209991</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/209991.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=209991</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Before I begin today's technical topic,&amp;nbsp;a quick link to what promises to be a &lt;EM&gt;terrifying&lt;/EM&gt;, I mean, &lt;EM&gt;terribly interesting&lt;/EM&gt; blog.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;Mario&lt;/STRONG&gt;, the guy who tests the code that I write and thereby keeps me honest, the guy who's application for a backyard barbecue was turned down by the Redmond fire department, the guy who, when I showed him how to use MSBUILD to change his security policy responded with "&lt;FONT color=#0000ff size=2&gt;wonderful! If&amp;nbsp;I was a woman I would kiss you... but because the lack of&amp;nbsp;some features a strong handshake is more appropiate for both of us,&amp;#8220; -- &lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;yes,&amp;nbsp;&lt;A href="http://blogs.msdn.com/windrago/"&gt;that guy has started blogging.&lt;/A&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;**********************************&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Today I'll give a more precise definition of how JScript .NET determines whether one type is assignable to another. Remember, &lt;STRONG&gt;assignable&lt;/STRONG&gt; is weaker than &lt;STRONG&gt;promotable&lt;/STRONG&gt; -- promotable means that we are &lt;STRONG&gt;guaranteed&lt;/STRONG&gt; that every instance of then source type is coercible to the target type.&amp;nbsp; With assignable, we care only if &lt;STRONG&gt;some instance&lt;/STRONG&gt; of the source type is coercible to the target type. &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Next time, we'll finish up this &lt;STRONG&gt;incredibly boring series&lt;/STRONG&gt; with the actual coercibility algorithm.&amp;nbsp; Then I think I'll take a short break and talk about some lighter topics before tackling overload resolution. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Again, suppose we have an assignment of an expression to a typed field. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Left Hand Side Expression = Right Hand Side Expression; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;where the compiler can infer the type of the left hand side as LHT and the right hand side as RHT.&amp;nbsp; I'm going to be a little bit loose in my definition of assignable below in that sometimes I care about the &lt;B&gt;&lt;SPAN&gt;type&lt;/SPAN&gt;&lt;/B&gt; of the right hand expression, but sometimes we have more information than just the type and we want to determine whether the &lt;B&gt;&lt;SPAN&gt;expression result&lt;/SPAN&gt;&lt;/B&gt; is assignable.&amp;nbsp; It should be clear from the context which way I mean it. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Unfortunately, the current release of JScript .NET has a number of bugs -- it appears that the compiler does not actually enforce some of these rules at compile time when it could.&amp;nbsp; Assigning bad constant strings to enumerated types, for example, isn't caught until runtime.&amp;nbsp; Neither is the rule for double-&amp;gt;single conversions.&amp;nbsp; Weird.&amp;nbsp; I'll mention those to the JScript .NET dev next time I see him.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We start with three broad categories: &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;RH Expression is a &lt;B&gt;&lt;SPAN&gt;compile-time constant. &lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;B&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;RH Expression is an &lt;B&gt;&lt;SPAN&gt;array literal. &lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;B&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;RH Expression is &lt;B&gt;&lt;SPAN&gt;something else. &lt;/LI&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/UL&gt;
&lt;P&gt;&lt;B&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;RHExp is a compile-time constant 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/B&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This is clearly the simplest case.&amp;nbsp; We know not only the type but the value, so the question of whether RHT is assignable to LHT or not is irrelevant.&amp;nbsp; All we care about is whether this specific expression is assignable. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If constant RHExp is the &lt;B&gt;&lt;SPAN&gt;name of a class&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHT &lt;B&gt;&lt;SPAN&gt;if and only if&lt;/SPAN&gt;&lt;/B&gt; LHT is &lt;B&gt;&lt;SPAN&gt;System.Type&lt;/SPAN&gt;&lt;/B&gt; or &lt;B&gt;&lt;SPAN&gt;System.Object&lt;/SPAN&gt;&lt;/B&gt;. &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is an &lt;B&gt;&lt;SPAN&gt;enumerated type&lt;/SPAN&gt;&lt;/B&gt; and RHExp is a &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHT &lt;B&gt;&lt;SPAN&gt;if and only if &lt;/SPAN&gt;&lt;/B&gt;the string names a member of that enumerated type. &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If the constant RHExp is coercible to type LHT then it is assignable.&amp;nbsp; (More on this next time.) &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If RHExp is a &lt;B&gt;&lt;SPAN&gt;numeric literal&lt;/SPAN&gt;&lt;/B&gt; and RHT is &lt;B&gt;&lt;SPAN&gt;8-byte float&lt;/SPAN&gt;&lt;/B&gt; and LHT is a &lt;B&gt;&lt;SPAN&gt;4-byte float&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHT. Yes, this is potentially lossy, but there's not much else we can do, so be careful!&amp;nbsp; However&amp;#8230; &lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If RHExp is a &lt;B&gt;&lt;SPAN&gt;compile-time constant 8-byte float&lt;/SPAN&gt;&lt;/B&gt; but NOT a numeric literal and LHT is a &lt;B&gt;&lt;SPAN&gt;4-byte float&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHT if and only if the string representation of the double and the string representation of that double downcast to single are identical.&amp;nbsp; (Oddly enough, this rule doesn't seem to be enforced by the compiler.&amp;nbsp; Looks like a bug.) &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;RHExp is an array literal 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/B&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Array literals are weird because they are treated as JScript arrays or system arrays depending on the context.&amp;nbsp; It matters very little what specifically RHExp is to determine assignment compatibility: 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;System.Object&lt;/SPAN&gt;&lt;/B&gt; or &lt;B&gt;&lt;SPAN&gt;System.Array&lt;/SPAN&gt;&lt;/B&gt; or &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHT &lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;not some kind of array&lt;/SPAN&gt;&lt;/B&gt; then RHExp is &lt;B&gt;&lt;SPAN&gt;not&lt;/SPAN&gt;&lt;/B&gt; assignable to LHT &lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;an array type of known rank and that rank is not 1&lt;/SPAN&gt;&lt;/B&gt; then RHExp is &lt;B&gt;&lt;SPAN&gt;not&lt;/SPAN&gt;&lt;/B&gt; assignable to LHT &lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;an array of known type ElemType&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHType &lt;B&gt;&lt;SPAN&gt;if and only if every element in the array literal is assignable to ElemType.&amp;nbsp; &lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;RHExp is something else.&lt;/STRONG&gt; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;System.Object&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable to LHT.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT &lt;B&gt;&lt;SPAN&gt;any primitive numeric type&lt;/SPAN&gt;&lt;/B&gt; and RHT is 8-byte float then RHT is assignable to LHT.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If RHT is &lt;B&gt;&lt;SPAN&gt;promotable&lt;/SPAN&gt;&lt;/B&gt; to LHT then obviously RHT is assignable to LHT.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is a &lt;B&gt;&lt;SPAN&gt;delegate&lt;/SPAN&gt;&lt;/B&gt; and RHExp is a &lt;B&gt;&lt;SPAN&gt;signature-compatible script function&lt;/SPAN&gt;&lt;/B&gt; then RHExp is assignable to LHT.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;not any kind of array&lt;/SPAN&gt;&lt;/B&gt; and RHT is &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; then RHT is &lt;B&gt;&lt;SPAN&gt;not&lt;/SPAN&gt;&lt;/B&gt; assignable to LHT.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;System.Array&lt;/SPAN&gt;&lt;/B&gt; and RHT is &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable to LHT.&amp;nbsp; (I believe this gives a warning though.)&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is an &lt;B&gt;&lt;SPAN&gt;array type known to be rank 1&lt;/SPAN&gt;&lt;/B&gt; and&amp;nbsp; RHT is &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable to LHT.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is an &lt;B&gt;&lt;SPAN&gt;array type known to be rank other than 1&lt;/SPAN&gt;&lt;/B&gt; and&amp;nbsp; RHT is &lt;B&gt;&lt;SPAN&gt;JScript array&lt;/SPAN&gt;&lt;/B&gt; then RHT is not assignable to LHT.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable -- just about everything can be converted to string.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;Boolean or any primitive numeric type&lt;/SPAN&gt;&lt;/B&gt; and RHT is &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable to LHT. &lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;char&lt;/SPAN&gt;&lt;/B&gt; and RHT is &lt;B&gt;&lt;SPAN&gt;string&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable to LHT. &lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT is &lt;B&gt;&lt;SPAN&gt;promotable&lt;/SPAN&gt;&lt;/B&gt; to RHT then RHT is assignable to LHT. For instance, base classes are assignable to derived classes even though they are not promotable.&lt;/LI&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If LHT and RHT are both &lt;B&gt;&lt;SPAN&gt;primitive numeric types&lt;/SPAN&gt;&lt;/B&gt; then RHT is assignable to LHT.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Those last four may give a compile-time warning, as they're pretty dodgy.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=209991" 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></item><item><title>JScript .NET Type Coercion Semantics, Part Two: Promotability</title><link>http://blogs.msdn.com/ericlippert/archive/2004/08/04/208435.aspx</link><pubDate>Thu, 05 Aug 2004 00:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:208435</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/208435.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=208435</wfw:commentRss><description>&lt;FONT face="lucida sans unicode" color=#800080 size=2&gt;
&lt;P&gt;Last time I gave some vague, high-level definitions of the type system concepts &lt;B&gt;promotable&lt;/B&gt;, &lt;B&gt;assignable&lt;/B&gt; and &lt;B&gt;coercible&lt;/B&gt;. Today I'll give a more precise definition of &lt;B&gt;promotable&lt;/B&gt;. The others I'll define more precisely later. &lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080 size=2&gt;Suppose we have an assignment of an expression to a typed field. &lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;
&lt;P&gt;Left Hand Side Expression = Right Hand Side Expression;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;where the compiler can infer the type of the left hand side as LHT and the right hand side as RHT. &lt;B&gt;RHT is promotable to LHT if every member of RHT is coercible to LHT.&lt;/B&gt; &lt;/P&gt;
&lt;P&gt;There are, as you'll see, some bugs and weirdnesses in JScript .NET's implementation of the promotability algorithm.&amp;nbsp;This describes how it is, not how it should be!&lt;/P&gt;
&lt;P&gt;In this list of rules there are some contradictions -- in those cases, earlier rules supercede later rules.&lt;/P&gt;&lt;B&gt;
&lt;P&gt;General rules&lt;/P&gt;&lt;/B&gt;
&lt;UL&gt;
&lt;LI&gt;If LHT &lt;B&gt;is the same type&lt;/B&gt; as RHT then RHT is trivially promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;System.Object&lt;/B&gt; and RHT &lt;B&gt;is a passed-by-reference type&lt;/B&gt; then RHT is &lt;B&gt;not&lt;/B&gt; promotable to LHT&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;System.Object&lt;/B&gt; and RHT is anything other than a passed-by-reference type then RHT is promotable to LHT&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;any non-array type&lt;/B&gt; and RHT is &lt;B&gt;an array type&lt;/B&gt; then RHT is &lt;B&gt;not&lt;/B&gt; promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;any array type&lt;/B&gt; then see the algorithm below.&lt;/LI&gt;
&lt;LI&gt;If LHT or RHT is an &lt;B&gt;enumerated type&lt;/B&gt; then see the algorithm below.&lt;/LI&gt;
&lt;LI&gt;If either RHT or LHT is a &lt;B&gt;class/interface&lt;/B&gt; then see the algorithm below.&lt;/LI&gt;
&lt;LI&gt;If RHT is the (single-member) &lt;B&gt;undefined&lt;/B&gt; type&amp;nbsp;or the (single member) &lt;B&gt;null&lt;/B&gt; type then RHT is promotable to LHT regardless of what LHT is. &lt;/LI&gt;
&lt;LI&gt;If LHT and RHT are both &lt;B&gt;primitive Boolean, numeric or date types&lt;/B&gt; (Boolean, 1/2/4/8 byte signed/unsigned integers, 4/8 byte floats, decimal, datetime, timespan), see the algorithm below.&lt;/LI&gt;
&lt;LI&gt;If LHT is a &lt;B&gt;JScript object wrapper for Boolean or string&lt;/B&gt; and RHT is the &lt;B&gt;corresponding primitive type&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is the &lt;B&gt;JScript object wrapper for number&lt;/B&gt; and RHT is &lt;B&gt;promotable to a primitive 8-byte float&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is the &lt;B&gt;primitive Boolean, string or datetime&lt;/B&gt; and RHT is the &lt;B&gt;corresponding wrapper type&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is a &lt;B&gt;primitive integer or float&lt;/B&gt; and RHT is the &lt;B&gt;wrapper type for number&lt;/B&gt; then RHT is promotable to LHT. (This one is an exception, as it is potentially lossy.)&lt;/LI&gt;
&lt;LI&gt;If LHT has &lt;B&gt;defined an implicit cast operator&lt;/B&gt; from RHT then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If RHT has &lt;B&gt;defined an implicit cast operator&lt;/B&gt; to LHT then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;Otherwise, RHT is not promotable to LHT.&lt;/LI&gt;&lt;B&gt;&lt;/UL&gt;
&lt;P&gt;Rules for the case where LHT is an array type&lt;/B&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If LHT is &lt;B&gt;any array type&lt;/B&gt; and RHT is &lt;B&gt;not an array type&lt;/B&gt; then&amp;nbsp;RHT is&amp;nbsp;&lt;B&gt;not&lt;/B&gt; promotable to LHT. &lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;not a JScript array&lt;/B&gt; and RHT is &lt;B&gt;a JScript array&lt;/B&gt; then RHT is &lt;B&gt;not&lt;/B&gt; promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;System.Array&lt;/B&gt; then RHT is promotable to LHT, regardless of RHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;any array type&lt;/B&gt; and RHT is &lt;B&gt;System.Array&lt;/B&gt; then RHT is &lt;B&gt;not&lt;/B&gt; promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is &lt;B&gt;a JScript array&lt;/B&gt; and RHT &lt;B&gt;is any array known to be of rank 1&lt;/B&gt; then RHT is promotable to LHT. Note that this is an exception, as it is potentially lossy or error-prone.&lt;/LI&gt;
&lt;LI&gt;If LHT is of &lt;B&gt;known type and rank&lt;/B&gt; and RHT is of &lt;B&gt;known type and rank&lt;/B&gt;, and furthermore, the &lt;B&gt;ranks are equal&lt;/B&gt; and RHT is &lt;B&gt;Element Type Compatible&lt;/B&gt; with LHT then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;Otherwise, RHT is not promotable to LHT.&lt;/LI&gt;&lt;B&gt;&lt;/UL&gt;
&lt;P&gt;Rules for the case where LHT or RHT is an enumerated type&lt;/P&gt;&lt;/B&gt;
&lt;UL&gt;
&lt;LI&gt;If LHT and RHT are &lt;B&gt;different enumerated types&lt;/B&gt; then RHT is not promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is an &lt;B&gt;enumerated type&lt;/B&gt; and RHT is a &lt;B&gt;primitive numeric type&lt;/B&gt; promotable to the &lt;B&gt;underlying numeric type&lt;/B&gt; of LHT them RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is a &lt;B&gt;primitive numeric type&lt;/B&gt; and RHT is an &lt;B&gt;enumerated type&lt;/B&gt; whose &lt;B&gt;underlying numeric type&lt;/B&gt; is promotable to LHT, then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If LHT is an &lt;B&gt;enumerated type&lt;/B&gt; and RHT is &lt;B&gt;string&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;Otherwise, RHT is &lt;B&gt;not promotable&lt;/B&gt; to LHT. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Note that the rules for enumerated types are exceptions; clearly there are always strings and numbers which are not coercible to a given enumerated type!&lt;/P&gt;&lt;B&gt;
&lt;P&gt;Rules for the case where RHT or LHT is a class/interface&lt;/P&gt;&lt;/B&gt;
&lt;UL&gt;
&lt;LI&gt;If&amp;nbsp;LHT is a &lt;B&gt;superclass&lt;/B&gt; of RHT then RHT&amp;nbsp;is promotable to LHT.&amp;nbsp;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;If&amp;nbsp;LHT is an &lt;B&gt;interface&lt;/B&gt; &lt;B&gt;implemented&lt;/B&gt; by RHT then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;Otherwise, RHT is &lt;B&gt;not promotable&lt;/B&gt; to LHT. &lt;/LI&gt;&lt;/UL&gt;&lt;B&gt;
&lt;P&gt;Rules for the case where RHT and LHT are both primitive types&lt;/P&gt;
&lt;UL&gt;&lt;/B&gt;
&lt;LI&gt;If RHT is &lt;B&gt;Boolean or unsigned 1-byte integer&lt;/B&gt; and LHT is &lt;B&gt;char, any&lt;/B&gt; &lt;B&gt;integer, float, decimal, datetime or timespan &lt;/B&gt;then RHT is promotable to LHT. &lt;/LI&gt;
&lt;LI&gt;If RHT is &lt;B&gt;char or unsigned 2-byte integer&lt;/B&gt; and LHT is &lt;B&gt;2-byte unsigned integer, any 4 or 8 byte integer, float, decimal, datetime or timespan&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If RHT is &lt;B&gt;signed 1/2-byte integer&lt;/B&gt; and LHT is &lt;B&gt;any signed integer, any float, decimal, datetime or timespan &lt;/B&gt;then RHT is promotable to LHT. (This appears to be buggy -- a signed 2-byte integer should not be promotable to a signed 1-byte integer! I'll look into it.)&lt;/LI&gt;
&lt;LI&gt;If RHT is &lt;B&gt;signed 4-byte integer&lt;/B&gt; and LHT is &lt;B&gt;signed 8-byte integer, 8-byte float, decimal, datetime or timespan&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If RHT is &lt;B&gt;unsigned 4-byte integer&lt;/B&gt; and LHT is &lt;B&gt;any 8-byte integer, 8-byte float, decimal, datetime or timespan&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If RHT is &lt;B&gt;any 8-byte integer&lt;/B&gt; and LHT is &lt;B&gt;decimal, datetime or timespan&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;If RHT is &lt;B&gt;any float&lt;/B&gt; and LHT is &lt;B&gt;8-byte float or decimal&lt;/B&gt; then RHT is promotable to LHT.&lt;/LI&gt;
&lt;LI&gt;Otherwise, RHT is not promotable to LHT.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Next time, assignability. &lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=208435" 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></item><item><title>JScript .NET Type Coercion Semantics</title><link>http://blogs.msdn.com/ericlippert/archive/2004/08/02/206216.aspx</link><pubDate>Mon, 02 Aug 2004 22:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:206216</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/206216.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=206216</wfw:commentRss><description>&lt;FONT face="Lucida sans unicode" color=#800080 size=2&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/slippman/archive/2004/08/01/204829.aspx"&gt;Stan Lippman has started an interesting series of blog entries &lt;/A&gt;on how Managed C++ determines which function &lt;FONT face="Lucida Console" color=#000080 size=2&gt;foo &lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;to call when you call &lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;foo(bar)&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt; given that there may be several visible functions of that name in the current scope.&amp;nbsp; That's quite coincidental, as just the other day &lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;I was going through some old mail&amp;nbsp;when I found a long document I wrote up on how JScript .NET does this. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#800080 size=2&gt;In the unlikely event that anyone out there is interested, I think I'll post bits of it over the next few days. The compare-and-contrast with C++ might be edifying. (Yes, this is going to be pretty geeky, even for me.)&lt;/P&gt;
&lt;P&gt;To begin with, I want to start by tackling a different question -- how does JScript .NET handle the situation where a value of one type is assigned to a field, where the field has a type restriction? For instance, how do we handle the situation&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;
&lt;P&gt;var blah : String = 123;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;? In particular, we are concerned with the &lt;B&gt;implicit&lt;/B&gt; type coercions. Explicit type coercions like&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;
&lt;P&gt;var blah : String = String(foo);&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;Are obviously less interesting, as the compiler does not have any particular work to do -- it just lets the run-time coercion function do its work.&lt;/P&gt;
&lt;P&gt;Recall that a type is defined as a &lt;B&gt;set of values, plus a set of rules for converting any values not in that set to a value in the set&lt;/B&gt;. (That rule may include "throw a type mismatch exception" of course!) For a quick refresher on the JScript and JScript .NET type systems in general, I wrote a whole series of articles starting &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/11/05/53336.aspxx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;here&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt;.&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#000080 size=3&gt;
&lt;P&gt;Under what circumstances are coercions performed?&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#800080 size=2&gt;The JScript .NET compiler can perform some type coercions at compile time. For instance, compile-time constants such as the above case can be converted by the compiler. But that's a pretty rare case. The more common case is that the &lt;B&gt;types&lt;/B&gt; are known at compile time but the &lt;B&gt;values&lt;/B&gt; are not.&amp;nbsp; (In the worst possible late-bound case the types are not known until runtime and special late-bound helper functions must be invoked. In general, the late-bound functions should have the same behaviour as if the types and values were known at compile time.)&lt;/P&gt;
&lt;P&gt;There are many situations in JScript .NET where the compiler must generate a type coercion. The most common cases are:&lt;/P&gt;&lt;/FONT&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;An explicit conversio&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;n (see above)&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;When assigning a value to a typed variable&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;When passing arguments to a function with typed arguments&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;When indexing an array&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;When setting a typed global value, local value or member value using an assignment operator (=, +=, etc).&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;When a function with a type annotation on its return type returns a value&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;Some operators cause arguments to be coerced, eg, (foo + "") coerces foo to string.&amp;nbsp;&amp;nbsp; Bitshift operators coerce arguments to 32 bit integers, etc.&lt;/LI&gt;&lt;/UL&gt;&lt;/FONT&gt;&lt;FONT face="Times New Roman" color=#800080 size=2&gt;&lt;/FONT&gt;&lt;FONT face="Times New Roman" color=#800080&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;There are also a few more obscure scenarios:&lt;/P&gt;&lt;/FONT&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;When passing arguments to a custom attribute.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;If a JScript array is coerced to a System.Array then each member of the JScript array is coerced to the element type of the System.Array.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;If a System.Array is coerced to a JScript array then we wrap the System.Array with a JScript array wrapper. Setting values on the JScript array wrapper automatically coerces the value to the element type of the underlying System.array. (See &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/11/10/53376.aspx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;here&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt;, &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/11/12/53377.aspx'"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;here&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt;, &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/11/14/53383.aspx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;here&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt;, &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/11/21/53399.aspx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;here&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt; and &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/12/05/53452.aspx"&gt;&lt;U&gt;&lt;FONT color=#0000ff size=2&gt;here&lt;/U&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT color=#800080 size=2&gt; for more information about the relationship between the two kinds of array.)&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;When subtracting anumber from a char the result is coerced to char -- I'll do another blog entry sometime on all the interesting semantics of the char type in JScript .NET.&lt;/LI&gt;&lt;/UL&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;&lt;FONT size=3&gt;How do we determine at compile time when an implicit coercion is legal?&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;I need some definitions.&lt;/FONT&gt;&lt;FONT face="Times New Roman"&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;By "&lt;B&gt;VALUE is coercible to TYPE&lt;/B&gt;" I mean that the &lt;B&gt;specific&lt;/B&gt; VALUE may be coerced to TYPE without data loss or error.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;For example, the value 0.5 is coercible to the type "32 bit floating point number" but not to the type "32 bit signed integer". (There are a few exceptions, in that some lossy coercions are still considered coercible -- numbers are considered coercible to Boolean, for instance.)&lt;/FONT&gt;&lt;FONT face="Times New Roman"&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;By "&lt;B&gt;TYPE_1 is promotable to TYPE_2&lt;/B&gt;" I mean that &lt;B&gt;every member&lt;/B&gt; of TYPE_1 is &lt;B&gt;coercible to&lt;/B&gt; TYPE_2. &lt;/P&gt;
&lt;P&gt;For example: the type "32 bit signed integer" is promotable to "64 bit float" but not promotable to "32 bit float".&amp;nbsp;Note that this implies that &lt;B&gt;any derived class is promotable to one of its base classes, and value types are always promotable to their boxed types.&amp;nbsp;&lt;/B&gt;&lt;/FONT&gt;&lt;FONT face="Times New Roman"&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;By "&lt;B&gt;TYPE_1 is assignable to TYPE_2&lt;/B&gt;" I mean that &lt;B&gt;there exists at least one member&lt;/B&gt; of TYPE_1 which is &lt;B&gt;coercible to&lt;/B&gt; TYPE_2. &lt;/P&gt;
&lt;P&gt;Clearly, if TYPE_1 is assignable to TYPE_2 but not promotable then there must be some member of TYPE_1 which is lossy or produces an error when coerced to TYPE_2. The JScript .NET compiler will&amp;nbsp;often issue a warning if the program contains an assignment entailing an implicit coercion&amp;nbsp;between types known to be&amp;nbsp;assignable but not promotable.&amp;nbsp; For example:&amp;nbsp; since zero is common to all numeric types, &lt;B&gt;all numeric types are assignable to each other&lt;/B&gt;.&amp;nbsp; &lt;B&gt;A base class is assignable to a derived class and vice-versa&lt;/B&gt;. But Array is not assignable to&amp;nbsp;Number.&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#800080 size=2&gt;Finally, a definition that will come in handy tomorrow: consider two typed array types, TYPE_1 and TYPE_2, where their elements are of type ETYPE_1 and ETYPE2, respectively. By "&lt;B&gt;TYPE_1 is element-type-compatible (ETC) to TYPE_2&lt;/B&gt;" I mean:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;If either ETYPE_1&amp;nbsp;or ETYPE_2&amp;nbsp;is a&amp;nbsp;&lt;B&gt;value type&lt;/B&gt; then TYPE_1 is ETC with TYPE_2 &lt;B&gt;if and only if ETYPE_1 = ETYPE_2&lt;/B&gt;.&amp;nbsp; &lt;FONT color=#000080&gt;int[]&lt;/FONT&gt; is not ETC with &lt;FONT color=#000080&gt;long[]&lt;/FONT&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT color=#800080 size=2&gt;If neither ETYPE_1 nor ETYPE_2 are value types then TYPE_1 is ETC with TYPE_2&lt;STRONG&gt; if and only if ETYPE_1 is promotable to ETYPE_2&lt;/STRONG&gt;. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;OK, enough definitions.&amp;nbsp; Why "assignable"? Because generally speaking, we can consider the pattern&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;Left Hand Side Expression = Right Hand Side Expression;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#800080 size=2&gt;as the canonical situation in which a type coercion is performed. When passing arguments to function calls, that's basically a kind of assignment. From now on we'll just talk about assignment coercions.&lt;/P&gt;
&lt;P&gt;The JScript .NET compiler determines the types of the LHS and RHS expressions at compile time as best it can and then checks to see if the RHS expression's type is &lt;B&gt;assignable&lt;/B&gt; to the LHS expression's type. If is it then it generates an implicit coercion. If it's assignable but not promotable, that's usually a warning, and if it is not assignable at all&amp;nbsp;then&amp;nbsp;that's usually a compile-time error.&lt;/P&gt;
&lt;P&gt;Next time I'll go into much more detail as to how the compiler determines promotability, assignability and coercibility.&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=206216" 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></item><item><title>A JScript .NET Design Donnybrook, Part Two</title><link>http://blogs.msdn.com/ericlippert/archive/2004/06/08/151209.aspx</link><pubDate>Tue, 08 Jun 2004 21:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:151209</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/151209.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=151209</wfw:commentRss><description>&lt;FONT face="Lucida Sans Unicode" color=#800080 size=2&gt;
&lt;P&gt;I am totally amused that the comments on &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/06/07/150367.aspx"&gt;yesterday's entry &lt;/A&gt;are nigh-isomorphic to the argument that we had over this in October 2000. As noted, &lt;FONT face="Lucida Console" color=#000080 size=2&gt;f.bar(f);&lt;/FONT&gt; does in fact call the base class function, not the derived class function as some might expect.&lt;/P&gt;
&lt;P&gt;I was on the fence back in 2000, but leaning towards the derived class, as was most of the rest of the team. Peter Torr was leaning towards the base class, and Herman, the architect, was pretty clearly in the base class camp. My argument was pretty similar to the arguments that most of you guys raised yesterday. In short, I&amp;nbsp;cleaved to the principle:&lt;/P&gt;&lt;B&gt;
&lt;P&gt;Calls to methods on objects of unknown type should have the same semantics as if the type was known to be the most derived type. If developers want to restrict a call to a method on a particular type, they can add the annotation.&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;Though that is clearly a decent principle, in this situation it conflicts with some other design principles, such as:&lt;/P&gt;&lt;B&gt;
&lt;P&gt;JScript is all about guessing what the developer meant to say, and muddling on through if it's not clear. &lt;/P&gt;&lt;/B&gt;
&lt;P&gt;and&lt;/P&gt;&lt;B&gt;
&lt;P&gt;Class-based code is a more-strictly-typed &lt;I&gt;alternative&lt;/I&gt; to dynamic prototype-based code, and therefore class semantics should&amp;nbsp;opt for increased&amp;nbsp;type safety and efficiency rather than increased dynamism.&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;It really comes down to guessing what the developer meant. My example was deliberately abstract. Consider a more realistic example. In Canada, there's a Goods and Services Tax which is rather complicated. There are situations where a&amp;nbsp;cake is taxable if you sell it in a restaurant, but not taxable if you sell it in a grocery store. (The rules are considerably more complex than that -- my father owned a restaurant at the time this tax became law, and figuring out when a single muffin vs a box of muffins&amp;nbsp;was taxable was&amp;nbsp;quite tricky.)&lt;/P&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;class Grocery {&lt;BR&gt;&amp;nbsp; function get tax() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;&lt;FONT color=#000080&gt;;&lt;BR&gt;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;&amp;nbsp; function PrintTaxrate(item) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print(item.tax);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;class Cake extends Grocery {&amp;nbsp;&lt;BR&gt;&amp;nbsp; &amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;hide&lt;/FONT&gt;&lt;FONT color=#000080&gt;&lt;FONT face="Lucida Console" size=2&gt; function get tax()&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;return 7&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#000080 size=2&gt;&lt;FONT color=#000080&gt;;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;BR&gt;Here the meaning of the "hide" is "&lt;EM&gt;if a cake is being treated as a cake, it's taxable. If it is being treated as a grocery item, it's not taxable&lt;/EM&gt;."&lt;/P&gt;
&lt;P&gt;But uh-oh, the developer of the base class did not annotate the method as taking a &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Grocery&lt;/FONT&gt;. &lt;/P&gt;
&lt;P&gt;Now, suppose that you are developing the &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Cake&lt;/FONT&gt; class. The &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Grocery&lt;/FONT&gt; class already exists, and you are extending it -- perhaps the base class is even in an entirely different &lt;FONT face="Lucida Console" color=#000080 size=2&gt;package&lt;/FONT&gt;. The developer of the &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Grocery&lt;/FONT&gt; class has forgotten to annotate the method, not anticipating that someone might have a &lt;B&gt;non-virtual override&lt;/B&gt;. In order to enable the developer of the &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Cake&lt;/FONT&gt; class to implement the desired semantics, the code gen for the &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Grocery&lt;/FONT&gt; class must as its first guess assume that the caller intended this thing to take a &lt;FONT face="Lucida Console" color=#000080 size=2&gt;Grocery&lt;/FONT&gt;. &lt;/P&gt;
&lt;P&gt;Clearly there are arguments on both sides; it's a judgment call whenever you have to guess what the user meant. &lt;/P&gt;
&lt;P&gt;Another advantage of this approach is that it is more efficient. Calling late-bound is very inefficient compared to speculatively casting the object to a class, and calling the method if the cast succeeds. The cost of late binding is enormous, and we wanted to do everything possible to eliminate it while still keeping the language scripty.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Therefore what the code gen does in this case is looks for every visible class which has the appropriate method, and generates a cast-and-call for each, and finally bottoms out to do the late-bound call if none of the casts worked. Unless you have a large number of visible classes with the same method names, this is pretty darn efficient. If you choose to always call the most derived type's method then there is no way to generate this code efficiently because you always must do the late bound call first.&lt;/P&gt;
&lt;P&gt;Philip Rieck's head exploded shortly after he discovered that the generated code actually checks to see if the argument is an instance of base, and THEN checks to see if it is an instance of derived. Isn't that unreachable code? Put your head back together Philip. Yes, it appears to be a codegen bug. I can't think of any circumstance in which that would not be dead code. I'll mention it to the JScript .NET team the next time I see him.&lt;/P&gt;
&lt;P&gt;Peter Torr might remember more reasons than I do why we chose to do it this way. Peter?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=151209" 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/Performance/default.aspx">Performance</category></item><item><title>A JScript .NET Design Donnybrook</title><link>http://blogs.msdn.com/ericlippert/archive/2004/06/07/150367.aspx</link><pubDate>Mon, 07 Jun 2004 21:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:150367</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/150367.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=150367</wfw:commentRss><description>&lt;DIV&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;When you're designing a new programming language, the "main line" cases are easy.&amp;nbsp; It's the "corner" cases that bedevil language designers -- the little fiddly bits where two language features that make perfect sense on their own interact in some weird way.&amp;nbsp; Unfortunately, I suspect that any language sufficiently feature-rich to be interesting will have weird corner cases.&amp;nbsp; Getting them right is one of the more interesting and difficult aspects of language design.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Want to give it a try yourself?&amp;nbsp; Now's your chance.&amp;nbsp; Here is a question that sparked a protracted and hilarious debate amongst the JScript .NET design team back in 2000.&amp;nbsp; I'd be interested to see what your opinions are.&amp;nbsp; So as to not spoil the fun, &lt;B&gt;&lt;SPAN&gt;figure out what you think this code should do &lt;I&gt;&lt;SPAN&gt;before&lt;/SPAN&gt;&lt;/I&gt; you run it or decompile it into IL.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;class foo &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp; function get abc()&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt; {&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#ff0000&gt;return 5&lt;/FONT&gt;;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp; }&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;class foo2 extends foo &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp; function bar(ob)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt; {&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print(ob.abc);&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp; }&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;class foo3 extends foo2 &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp; &amp;nbsp;&lt;FONT color=#ff0000&gt;hide&lt;/FONT&gt; function get abc()&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt; {&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#ff0000&gt;return 50&lt;/FONT&gt;;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp; }&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;var f = new foo3();
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Clearly &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;print(f.abc); &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;must print out &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;50&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; But should &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;f.bar(f); &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;print out &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;50&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;5&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;?&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Justify your answer.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;HINT: While you're thinking it over, keep in mind that nowhere in this code are there any type annotations.&amp;nbsp; The question was originally raised in the context of speculative compiler optimizations which we might perform in the absence of type annotations.&amp;nbsp; Are there codegen optimizations which we could perform that make your desired behaviour more efficient in common cases?&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=150367" 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/Performance/default.aspx">Performance</category></item><item><title>JScript .NET Classes Are Serializable -- Surprise!</title><link>http://blogs.msdn.com/ericlippert/archive/2004/05/26/142687.aspx</link><pubDate>Thu, 27 May 2004 00:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:142687</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/142687.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=142687</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;You learn something new every day in this job.&amp;nbsp; Or, more accurately, some days you learn things again that you'd forgotten years ago.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Someone just asked me why it is that all JScript .NET classes are serializable.&amp;nbsp; I admit it, my first reaction was "They are?"&amp;nbsp; But I checked the sources, wrote some code and ran it through ILDASM and sure enough, all JScript .NET classes ARE serializable!&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Though I did not write that code,&amp;nbsp;surely I&amp;nbsp;must have known that at &lt;EM&gt;some&lt;/EM&gt; point.&amp;nbsp; Now that I think about it a bit more, it's coming back to me.&amp;nbsp; I think the idea was that the designers anticipated that there would often be situations in which JScript.NET objects would have to be passed across appdomains.&amp;nbsp; (Exceptions for instance -- in JScript, you can throw anything.) That means either making classes marshal-by-ref or serializable, and apparently we picked serializable.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We could of course have gone the other way, and made developers figure out which classes needed to be serialized, and defaulted to &amp;#8220;not serializable&amp;#8220;.&amp;nbsp; But one of the major JScript .NET design principles is "just get it done, already!"&amp;nbsp; C# was designed so that most of the defaults limit behaviour -- things are private until made public, and so on.&amp;nbsp; In JScript .NET, as much as possible is left open; if you want to tighten it up, you go right ahead.&amp;nbsp; This is in keeping with the scripty nature of the language, while still recognizing that people do write large programs in script languages.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If for some reason you wish a class to be not serializable&amp;nbsp;then you can do this:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public System.NotSerialized class MyClass {
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Times New Roman" size=3&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;(Notice that in JScript .NET, you don't need to put ugly brackets around attributes.&amp;nbsp; The parser is smart enough to figure out that there is an attribute before the class declaration.&amp;nbsp; However, this significantly complicates the parser; I see why C# and VB.NET require their delimeters.)
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Offhand I don't see anywhere on MSDN where this feature is documented, though it is possible that my google-fu has failed me.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=142687" 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></item><item><title>Eval is Evil, Part Three</title><link>http://blogs.msdn.com/ericlippert/archive/2004/01/26/63087.aspx</link><pubDate>Mon, 26 Jan 2004 19:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:63087</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/63087.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=63087</wfw:commentRss><description>&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;SPAN&gt;
&lt;DIV&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Recall that in &lt;A title=http://blogs.msdn.com/ericlippert/archive/2003/11/01/53329.aspx HREF="/ericlippert/archive/2003/11/01/53329.aspx"&gt;Part One&lt;/A&gt; we discussed &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; on the client, and in &lt;A title=http://blogs.msdn.com/ericlippert/archive/2003/11/04/53335.aspx HREF="/ericlippert/archive/2003/11/04/53335.aspx"&gt;Part Two&lt;/A&gt; we discussed &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; on the server.&amp;nbsp; Today, I answer a question about &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in JScript .NET. S&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;omeone sent me mail the other day asking why this C# program snippet didn't work:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;x = Microsoft.JScript.GlobalObject.eval("1");&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This throws a seemingly bizarre exception.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Microsoft.JScript.JScriptException: Eval may not be called via an alias
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What's up with that?&amp;nbsp; Well, remember that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; parses and executes a program snippet &lt;B&gt;&lt;SPAN&gt;in the context of an existing runtime state&lt;/SPAN&gt;&lt;/B&gt;. &amp;nbsp;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;For example, consider this JScript program:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;var x = 123;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;var y = eval("x + 10");
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;How does &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; know to return 133?&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; &lt;B&gt;&lt;SPAN&gt;needs to know what the current state of the runtime is&lt;/SPAN&gt;&lt;/B&gt; -- what all the variable bindings are, what scope it is presently in, all that kind of stuff.&amp;nbsp; You can't just up and call a general purpose evaluation engine from no context whatsoever.&amp;nbsp; Eval isn't a calculator!&amp;nbsp; &lt;B&gt;&lt;SPAN&gt;It's deeply integrated with the JScript .NET runtime.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If you want to call eval, there are only two legal ways to do so
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;1)&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Write a JScript .NET&amp;nbsp;program that calls &lt;SPAN&gt;&lt;FONT face="Lucida Console" color=#000080&gt;eval&lt;/FONT&gt;&lt;/SPAN&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;/FONT&gt;explicitly.&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;2)&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Construct a &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;VsaEngine&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; containing the desired runtime state, and then call the public static function &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Eval.JScriptEvaluate(source, engine)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;I don't recommend the second option&lt;/STRONG&gt; unless you &lt;EM&gt;really&lt;/EM&gt; know what you are doing.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;But what's up with that bizarre exception? Actually, the exception was not designed to catch people trying to call &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; without a runtime context. Though that certainly is a nice side effect, we would have made the error message a little more clear had this been the primary scenario!
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;An &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; precludes certain compiler optimizations, so we must detect at compile time whether a given scope contains an &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;. Easy -- just look for calls to that function, right? But you could get around that by aliasing &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Remember, JScript has first class functions, so nothing stops you from saying
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;function foo(x)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;var abc = 123;&amp;nbsp;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // The compiler detects that only numbers are &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // assigned to abc and optimizes accordingly&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x("abc = 'hello';");&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // but if x is eval then the optimization is incorrect&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ...&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;foo(eval)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=purple size=2&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We have no way of determining whether or not &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;foo&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; contains a call to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; &lt;B&gt;&lt;SPAN&gt;Therefore we made aliasing &lt;/SPAN&gt;&lt;/B&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;B&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; illegal.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; Now the exception makes sense: &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Eval may not be called via an alias&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;. The program above produces that exception.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;But why is this exception thrown when a C# programmer tries this?
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;x = Microsoft.JScript.GlobalObject.eval("1");&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Because if the compiler &lt;B&gt;&lt;SPAN&gt;finds&lt;/SPAN&gt;&lt;/B&gt; a call to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, it generates a special function call node in the abstract syntax tree which generates different code than the general purpose function call node that would be generated for the case above.&amp;nbsp; When you say in JScript .NET
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval(whatever);
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;then the compiler generates a call to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Eval.JScriptEvaluate(source, engine)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;. After all, the compiler knows where the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;VsaEngine&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; state is.&amp;nbsp; But if you get a reference to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;eval&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; via the global object -- either directly in the C# case, or indirectly in the JScript .NET case --&amp;nbsp;then you get a dummy function that just throws an exception.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;There are also security implications to using &lt;SPAN&gt;&lt;FONT face="Lucida Console" color=#000080&gt;eval &lt;/FONT&gt;&lt;/SPAN&gt;in JScript .NET which I will get into in a future post.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=63087" 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></item><item><title>Virtual Methods and Brittle Base Classes</title><link>http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx</link><pubDate>Wed, 07 Jan 2004 23:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:48399</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/48399.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=48399</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Hey, I'm back! And in my new location. 
&lt;P&gt;That was the longest and least relaxing vacation I've ever taken. Fun, yes. Relaxing, no. And to top it off, my kitchen is not done yet. We're shooting for being able to run water tonight and actually use appliances by tomorrow night, but we'll see how it goes. 
&lt;P&gt;Well, enough chit-chat. I wanted to talk a little about the brittle-base-class problem, and how JScript .NET deals with it. 
&lt;P&gt;&lt;U&gt;Virtual Methods and Brittle Base Classes&lt;/U&gt; 
&lt;P&gt;One of the challenges inherent in writing larger programs is managing change over time. Few large programs are written once and never updated. Usually new features are implemented for new versions. Class-based programming allows for clean, object-oriented design but there are still some pitfalls to be wary of. One of the more insidious object-oriented programming pitfalls is the &lt;B&gt;brittle base class problem&lt;/B&gt;. Here's how it usually goes: 
&lt;P&gt;You develop a very useful class for version one of your project. You have a "gadget" which can be "confusticated": 
&lt;P&gt;&lt;SPAN class=code&gt;// Project Juliet Version 1 &lt;BR&gt;class Gadget { &lt;BR&gt;&amp;nbsp; public function confusticate() { // . . . &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Some coworkers working on another application at your company realize that their "widgets" are a special case of your gadgets, so they subclass. After all, code re-use is one of the benefits of object-oriented programming. These particular widgets need to be "garbled", so they add a new method: 
&lt;P&gt;&lt;SPAN class=code&gt;// Project Romeo Version 1 &lt;BR&gt;class Widget extends Gadget { &lt;BR&gt;&amp;nbsp; public function garble( ) { // . . . &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;A widget is confusticated the same as a gadget, thus they do not override the &lt;SPAN class=code&gt;confusticate&lt;/SPAN&gt; method. They get your library, compile up their code, test everything out and it is all good. 
&lt;P&gt;Six months after version one of your project ships you are hard at work developing the next version. In this version you have decided that gadgets can be garbled too. Furthermore, you decide that any confusticated gadget needs to also be garbled, so you modify your sources: 
&lt;P&gt;&lt;SPAN class=code&gt;// Project Juliet Version 2 &lt;BR&gt;class Gadget { &lt;BR&gt;&amp;nbsp; public function garble() { // . . . &lt;BR&gt;&amp;nbsp; public function confusticate() { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.garble(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // . . . &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;You have no idea that your coworkers have extended your class and already added a method to garble a widget. Furthermore, &lt;B&gt;they do not necessarily know that you have changed the base class.&lt;/B&gt; That could be a very small change amongst thousands of lines of code and many other changes. Now what happens when they call &lt;SPAN class=code&gt;confusticate&lt;/SPAN&gt; on one of their widgets? The base class's &lt;SPAN class=code&gt;confusticate&lt;/SPAN&gt; method is called, but because &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; is virtual it then calls the derived class's &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; method. 
&lt;P&gt;There are two ways that could be seriously wrong. First of all, you might have implemented the base class fully expecting that the &lt;I&gt;gadget&lt;/I&gt; garbling method would be called upon confustication, but now the &lt;I&gt;widget&lt;/I&gt; garbling is performed. Second, &lt;B&gt;the widget implementers have no idea that confusticating can cause garbling.&lt;/B&gt; From their perspective the only code that can call &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; is &lt;I&gt;their&lt;/I&gt; code! &lt;B&gt;As far as they know they are the only ones who have written a garbling method.&lt;/B&gt; 
&lt;P&gt;"Base" classes are well-named -- the behaviour of the derived classes depends upon the base classes having rock-solid behaviour. If the base class implementations are brittle, then the derived classes will not be robust either. This is just one brittle base class scenario; there are many variations on this scenario. 
&lt;P&gt;One way to prevent the brittle base class problem is to use assembly manifests and config files to ensure that you always bind against the version you tested against. But in the spirit of providing the flexibility of multiple solutions, JScript .NET also affords some techniques to mitigate the rittle base class problem. 
&lt;P&gt;&lt;U&gt;Trapping the Error: The Versionsafe Switch&lt;/U&gt; 
&lt;P&gt;The lesson here is that every time you change a base class you have to test not only the base class but every single derived class. There really is no getting around that fundamental fact but there is a tool which can help in this particular situation. If you run the JSC compiler with &lt;SPAN class=code&gt;/versionsafe&lt;/SPAN&gt; then the potential disaster described above will not be &lt;I&gt;averted&lt;/I&gt; but it will at least be &lt;I&gt;brought to your attention&lt;/I&gt;. Specifying this flag makes it illegal to make a virtual function by accident. In other words, it changes the default behavior from "make a function with the same signature as a base class function an overriding virtual function" to " make a function with the same signature as a base class function an error." 
&lt;P&gt;That means that when the people working on Project Romeo version 2 go to compile up the Widget class using the new &lt;SPAN class=code&gt;Gadget&lt;/SPAN&gt; they will &lt;I&gt;immediately&lt;/I&gt; get an error. You have added a &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; method which matches the signature in a base class and they must therefore explicitly say whether their matching method is a virtual (override) or a non-virtual (hide) method. Which solution is correct depends on the semantics of all the interacting methods; the point is to flag the potential problem automatically rather than using a default behavior which might be incorrect. 
&lt;P&gt;&lt;U&gt;Preventing the Subclassing&lt;/U&gt; 
&lt;P&gt;The crux of the brittle base class problem is that the providers of the base and derived classes each have no idea what the other is doing. It is extremely annoying to have bugs crop up that seem to be in your code because someone else did a poor job of writing a subclass. It is possible and indeed highly desirable to simply not let anyone subclass your classes without a compelling reason. 
&lt;P&gt;The attribute &lt;SPAN class=code&gt;final&lt;/SPAN&gt; is used to indicate that a class may not be subclassed in JScript .NET: 
&lt;P&gt;&lt;SPAN class=code&gt;final class Gadget &lt;BR&gt;{ /* . . . */ } &lt;/SPAN&gt;
&lt;P&gt;Now when your coworkers try this, they get an error: 
&lt;P&gt;&lt;SPAN class=code&gt;class Widget extends Gadget // Error, Type Gadget may not be extended &lt;BR&gt;{ /* . . . */ } &lt;/SPAN&gt;
&lt;P&gt;It might be the case that you do want &lt;SPAN class=code&gt;Gadget&lt;/SPAN&gt; to be extendible but do not want a particular method to be overridden. To do this you can make individual functions final: 
&lt;P&gt;&lt;SPAN class=code&gt;class Gadget { &lt;BR&gt;&amp;nbsp; final public function Garble() { // . . . &lt;BR&gt;} 
&lt;P&gt;class Widget extends Gadget&amp;nbsp;{&amp;nbsp;// OK, Gadget is not final&amp;nbsp;&lt;BR&gt;&amp;nbsp; override public function Garble() { // Error, Garble is final &lt;/SPAN&gt;
&lt;P&gt;Note that &lt;B&gt;it is legal to &lt;I&gt;hide&lt;/I&gt; a final base class method&lt;/B&gt;. It is only illegal to &lt;I&gt;override&lt;/I&gt; a final base class method. 
&lt;P&gt;Another technique would be to use inheritance demands, but that's a topic for another day. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=48399" 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/Brittle+Base+Classes/default.aspx">Brittle Base Classes</category></item><item><title>The JScript Type System Part Eight: The Last Blog Entry About Arrays, I Promise</title><link>http://blogs.msdn.com/ericlippert/archive/2003/12/05/53452.aspx</link><pubDate>Fri, 05 Dec 2003 21:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:53452</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/53452.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=53452</wfw:commentRss><description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;
    &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; 
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Recall
        that I defined a &lt;em&gt;type&lt;/em&gt; as consisting of two things: a &lt;strong&gt;set&lt;/strong&gt; of
        values, and a &lt;strong&gt;rule&lt;/strong&gt; for associating values outside of that set with
        values inside the set.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;In JScript .NET,
        assigning a value outside of a type to a variable annotated with that type restriction
        does that coercion if possible&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;var s
        : String = 123; // Converts 123 to a String&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Similarly,
        I already discussed what happens when you assign a JScript array to a hard-typed CLR
        array variable&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;var sysarr
        : int[] = [10, 20, 30]; // Create new int[3] and copy 
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;and
        what happens when you assign a one-dimensional CLR array to a JScript array variable:&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;var jsarr
        : Array = sysarr; // Wrap sysarr 
        &lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;But
        what happens when you assign a &lt;b style="mso-bidi-font-weight: normal"&gt;hard-typed
        CLR array&lt;/b&gt; to a variable annotated with a &lt;b style="mso-bidi-font-weight: normal"&gt;different&lt;/b&gt; CLR
        array type?&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;var intarr
        : int[] = [10, 20, 30];&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;var strarr
        : String[] = intarr;&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;You
        might think that this does the string coercion on every element, but in fact this
        is simply not legal. Rather than creating a copy with every element coerced to the
        proper type, the compiler simply gives up and says that these are not type compatible.
        If you find yourself in this situation then you will simply have to write the code
        to do the copy for you.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Something like
        this would work:&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;function
        copyarr(source : System.Array) : String[]&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;var
        dest : String[] = new String[source.Length];&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;for(var
        index : int in source)&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;dest[index]
        = source.GetValue(index);&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;return
        dest;&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;There
        are a few notable things about this example. First, notice that this copies a rank-one
        array of any element type to an array of strings. This is one of the times when it
        comes in handy to have the &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;System.Array&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; "any
        hard-typed array" type!&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Second,
        notice that you can use the &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;for-in&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; loop
        with hard-typed CLR arrays. The for-in loop &lt;b style="mso-bidi-font-weight: normal"&gt;enumerates
        all the indices of an array rather than the contents of the array.&lt;/b&gt; Since CLR arrays
        are always indexed by integers the index can be annotated as an int. The loop above
        is effectively the same as&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;for (var
        index : int = 0 ; index &amp;lt; source.Length ; ++index)&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;but
        the &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;for-in&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; syntax
        is less verbose and possibly more clear.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Third,
        you might recall that &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;GetValue&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt; (and &lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: #333399; FONT-FAMILY: 'Lucida Console'"&gt;SetValue&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;)
        take an &lt;b style="mso-bidi-font-weight: normal"&gt;array&lt;/b&gt; of indices because the array
        might be multidimensional. But we're not passing in an array here.&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;Fortunately,
        you can also pass only the index if it is a single-dimensional array.&lt;o:p&gt;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;
        &lt;o:p&gt;&amp;#160;&lt;/o:p&gt;
        &lt;/span&gt;
    &lt;/p&gt;
    &lt;p class="MsoNormal" style="MARGIN: 0in -5.65pt 0pt 0in"&gt;
        &lt;span style="FONT-SIZE: 10pt; COLOR: purple; FONT-FAMILY: 'Lucida Sans Unicode'; mso-bidi-font-family: 'Times New Roman'"&gt;Generally
        speaking,&amp;#160;&lt;strong&gt;hard-typed array types are incompatible with each other.&lt;/strong&gt; There
        is an exception to this rule, which I'll discuss later when I talk about what exactly
        "subclassing" means in JScript .NET.&lt;/span&gt; 
    &lt;/p&gt;
    &lt;/span&gt;
&lt;/body&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=53452" 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/Scripting/default.aspx">Scripting</category></item></channel></rss>