April 2004 - Posts
One of the discussions on one of the CLI mailing lists (on the ximian.com server), I raised the idea of adding
Covariant Return Types to the CLS.
At the moment, the only responder, Jonathan Pryor from the Mono team,
has answered me with some very interesting points.
For those of you who are not in that list, here is the transcript.
Here are a few quotes from the list:
Covariant Return Types support means that you will be able to write the following code:
public class ClassA { }
public class ClassB : ClassA { }
public class MyClass
{
public virtual ClassA DoSomething()
{
// Work magic...
// Return an instance of type ClassA.
}
}
public class MyDerivedClass : MyClass
{
public override ClassB DoSomething()
{
// Work magic...
// Return an instance of type ClassB.
}
}
This would mean that I could use a derived type as the return type for overriding methods.
This check could be very easy, since method signatures do not vary on the basis of their return type.
The greatest advantage this embodies is the ability to type the return value for specific implementations of derived
types.
A great addition to this (I'm not sure if this is included in the definition) could be this:
public class MyClass : System.Object, System.IClonable
{
public MyClass Clone()
{
// Return a copy of the current object.
}
}
This would mean that return types for implemented methods could be altered in the same fashion.
- Omer van Kloeten
To which the reply was:
<snip/>
They could be useful. However, to be truly useful they'd need to be part of the Common Language Specification (CLS).
Additionally, covariant return types still wouldn't be needed, as the method overloading technique used by C# is
virtually required for decent use of the class libraries. Consider: System.Collections.IEnumerable and
System.Collections.IDictionary both provide the GetEnumerator() method, but with different return types. Also note that
IDictionary implements the IEnumerable interface.
Thus, if a language wants to allow developers to implement the standard IDictionary interface, the language *must*
permit explicit method implementation (permitting separate implementations of the IEnumerable.GetEnumerator() and
IDictionary.GetEnumerator() methods).
- Jonathan Pryor
My Reply:
<snip/>
You are correct, the language would have to permit explicit interface implementation to use both interfaces.
However, let's look at your example from another perspective: Why does the IDictionary interface declare this
method?
The IDictionary.GetEnumerator() method is only there because there are no Covariant Return Types, meaning the
interface can not implicitly convert the return type of the inherited method, thus requiring it to create a new
definition with the needed return type.
This is one of the types of confusion Covariant Return Types come to prevent.
- Omer van Kloeten
He Replied:
<snip/>
To return to the original question, should covariant return types be supported by the runtime, I still believe that
the answer is "no". Explicit method implementation is a sufficient replacement, at least at the IL level.
Individual languages can support covariant return types, with the compiler for those languages using the explicit
method implementation approach when generating code, and looking for similar method overloading patterns when consuming
existing code. This permits maximum flexibility -- languages without support for covariant return types can still get
similar benefits with explicit methods, and users of languages supporting covariant return types reap the benefits of
less typing. :-)
- Jonathan Pryor
I snipped some parts that I think were not really important. If I have removed something of significance, please let me
know.
Well, this is still being talked about. Feel free to comment here or join in if you have some good input on the
matter.
nGineer is a language analysis and code generation kit for .NET languages and specifically C# which is currently being developed.
Components of nGineer are released separately and more components will be released soon.
The CodeDOM Generator component of the nGineer component suite persists Code Document Object Model object grids to Code Document Object Model object grids of themselves.
This would mean that if your tool generates a grid of Code DOM objects and you would like to see what that code would look like should it have been written as code, just send it through the CreateDOM method of the nGineer.CodeDOMGenerator class and you will receive a CodeCompileUnit with the code generated for your object grid.
The code is simple. Just type:
CodeCompileUnit generatedUnit = nGineer.CodeDOMGenerator.CreateDOM(unit);
Check out the project's page for examples and downloads.
This is important to all of you users of Windows 2000 Hebrew out there. I don't usually post this kind of things, but this is a good venue.
I have been having problems with the latest updates from Microsoft with the Hebrew in my taskbar being reversed when a window's title is mixed Hebrew and English.
After consulting people in the Microsoft newsgroups, I have come to understand that the fault relies in KB835732. I have uninstalled it and things returned to normal.
If anyone has any information on why this happens or when a fix is issued to this problem, please notify me. :)
[Update: I would rather have my Hebrew reversed than be attacked by the Sasser Worm. Reinstalled and grunting. ]
I was at a code review for one of the developers when I came across the following lines of code:
public void DoSomething(int value)
{
switch (value)
{
case (int)SomeEnum.Value1:
DoThis();
break;
case (int)SomeEnum.Value2:
DoThat();
break;
}
}The intention behind these lines was getting a value that was a value of the enum without having to expose the enum itself. In this case, the value was given by direct input from the user.
It might be obvious to some of you, but this code section has a few flaws. First of all, there is no check for the value and there is a conversion to the integer type for every case statement.
So I dug into the IL and found that one of these things was not even a problem: The code is compiled so that the values of the enum are translated to strongly typed integer values. This means that it doesn't really matter, IL-wise, if you convert the value in the switch to the enum or each value to integer, it comes out the same.
What did bother me was the fact that this programmer didn't check if the value sent to the method was even a valid value. This is done by using the Enum.IsDefined method and checks that the value passed is a defined value in the enum's range of values.
Code should describe itself. This is a statement everyone agrees on.
Whether or not comments should add to this description is somewhat of an everlasting debate.
I'd like to present you with a question:
One rule in a system declares that "an integer that's value is not greater than 8 is a valid X" (sic).
Another rule in that system declares that a certain variable should "not be a valid X" (sic).
It was decided that there should not be a method returning a boolean value whether or not an integer was a valid X or not and 8 should not be a constant.
How would you decide to write this?
The obvious answers would be:
1. (!(!(myVariable > 8))).
2. (!(myVariable <= 8)).
3. myVariable > 8.
I would rather write the code using option 1. In my opinion, it best describes the situation, since the documentation declares that "myVariable should not be X" and if expanded, we get a double negation which reads "myVariable should not be a value that is not greater than 8".
If your first thought was "You're saying that you'd rather do two more operations (not and not) in order to do something I could do with one operation with option 3", then I can tell you that it all comes down to the exact same IL, thanks to the compiler.
What do you think?
[Update: Some very interesting conversation in the feedback. Be sure to look into it.]
I'll be putting to writing all I know about the Code Document Object Model.
This means that you will be getting a series of articles regarding all aspects of the Code DOM, and since not too much clear information exists about this on the web, I think it might come in handy to many of you out there.
The articles are here and I will be editing this post whenever I complete typing in a part of it. So far, parts I, II, III and IV are up for grabs.
Latest Update: Part IV now with overdue examples and 10% less monosodium glutamate!
Please feel free to comment about any part of the article.
Please send any spelling, grammar or content mistakes you find via the contact page.
Here are a couple of tips and tricks with code generation for C#:
- You do not have to send a parameter of type CodeGeneratorOptions to the GenerateCodeFromCompileUnit method. null is sufficient.
- The CodeGeneratorOptions class contains some interesting things, like the BracingStyle property. Setting this to "C", instead of the default "Block" (funny how there are no constants for these) will format your code more nicely, conforming more to the format done by Visual Studio.NET's reformatting (Ctrl+A, Ctrl+K+F).
- I looked into this after Roy asked me about it: Verbatim string literals (strings prepended by a @) will only be generated if the string's size is between 256 and 1500 characters long. And it always will. This means that if your string is less that 256 characters long or 1500 or more characters long it will always be generated as a regular string literal. Otherwise, it will always be generated as a verbatim string literal.
I found this using Reflector, but didn't understand why. Looking through Rotor for an answer, I found it here on line 317, where it says that:
// If the string is short, use C style quoting (e.g "\r\n")
// Also do it if it is too long to fit in one line
Funny how this shows nowhere in the documents, is typed into the code and there are no constants or properties to change this...
By the way, for those of you who care only for my CodeDOM posts, I added a new category to my weblog, CodeDOM Adventures.
I won't be offended if you choose to only subscribe to those. No, really. ;)
I have just placed version 0.4 of the binary, source and the experimental Visual Studio .NET 2003 plugin of the Object Model Generator on its web page.
Among the improvements:
- Any Attribute Support.
- Element Inner Text Support.
- Constants for Element / Attribute Names.
- Lots of Bug Fixes. A lot! Really!
Please note that the examples have also been updated.
Happy Passover/Easter, Everyone!
More Posts