May 2005 - Posts

Using Statements

From a completely unrelated Google search I came across this post by Fritz Onion over on pluralsight mentioning that he was happy to see Visual Basic 2005 adopting the C# using statement to make resource management a little easier in VB. He went on to concede that it wasn’t quite as elegant as the corresponding C#. Here is the VB example he provided:

Using conn As New SqlConnection(dsn)
  Using cmd As New SqlCommand("SELECT * FROM Employees", conn)
    conn.Open()
      Using rdr As SqlDataReader = cmd.ExecuteReader()
        While rdr.Read()
          Console.WriteLine(rdr(0))
        End While
      End Using
  End Using
End Using

And here is the C# version he compared it to:

using (SqlConnection conn = new SqlConnection(dsn))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Employees", conn))
{
  conn.Open();
  using (SqlDataReader rdr = cmd.ExecuteReader())
  {
    while (rdr.Read())
       Console.WriteLine(rdr[0]);
  }
}

I can’t help but point out that VB and C# have nothing on C++ when it comes to resource management. Here is the corresponding code written in C++:

SqlConnection conn(dsn);
SqlCommand cmd("SELECT * FROM Employees", %conn);
conn.Open();
msclr::auto_handle<SqlDataReader> rdr(cmd.ExecuteReader());

while (rdr->Read())
{
    Console::WriteLine(rdr->GetValue(0));
}

Not only is this easier to write IMHO, but more importantly the code is correct by default. More on C++ in my upcoming book: Applied Visual C++ 2005. I’ve made a general rule for myself as I write the book that I should stay away from comparing C++ to other languages, with the exception of IL. So this blog helps me to vent.

:)

Don’t get me wrong. C# is a fun language which I’ve been forced to had the pleasure of using a fair amount over the last few years. It certainly has some language and compiler features (in version 2.0) that I wish we had in C++. VB on the other hand… [insert some Don Box crack about a semicolon-starved language].


© 2005 Kenny Kerr

Posted by KennyKerr with 11 comment(s)

Applied Visual C++ 2005

I haven’t been blogging much over the last few months mostly because I’ve been real busy on various projects, the most significant being my new book entitled Applied Visual C++ 2005. Hopefully I will be able to write more about it in the coming weeks. In a nutshell, it introduces Visual C++ 2005 as a language and compiler for developing applications targeting the .NET Framework.

Part 1 sets the foundation by exploring the fundamentals that you need to be familiar with in order to start writing managed as well as mixed mode (containing both native and managed code) applications. I hope to complete part 1 of the book and get it out to reviewers by the end of the month.

I came across a quote from Douglas Adams in the commentary of one of his books that I think all authors must appreciate:

“I love deadlines. I like the whooshing sound they make as they fly by.”

Here is the outline for part 1:

Ch1 – Hello .NET
(How to set up projects and build your first console application)

Ch2 – A New Runtime and Type System
(How the CLR relates to the OS and CRT and how it’s exposed in Visual C++)

Ch3 – Types and Abstractions
(How to define managed types and members)

Ch4 – Member Functions
(Member functions in depth)

Ch5 – From Pointers to Handles
(How different forms of object references work and are applied in different scenarios)

Ch6 – Exceptions and Exception Handling
(How to define and use managed exceptions alongside native C++ exceptions)

Ch7 – Generic Programming
(How CLR generics compare to C++ templates and how to use them both effectively)

Part 1 of the book is relatively short. I don’t attempt to introduce the CLR in detail. Rather it focuses on providing a practical introduction to C++/CLI and explaining enough of how the CLR works for it all to make sense.

Part 2 focuses on the .NET Framework’s extensive class library, exploring some of the most generally useful and powerful libraries. Each chapter in part 2 also includes a realistic sample project that is explored in detail to provide practical and generally applicable sample code for the reader. As this book is geared at providing lots of practical information that can be directly applied to real-world applications, each chapter considers aspects of native as well as managed code and libraries.

You may be saying to yourself: “I know the .NET Framework already. What can this teach me?” As much as the CLR is a “common language runtime”, the language you choose to view it through has a significant impact on your view of managed code. This is witnessed in books like Richter, which although an excellent book providing great insight into the .NET Framework, paints a rather language centric view of the framework. You can also see this in the design of some parts of the .NET Framework. In part 2 of this book my aim is to present a more C++ centric view of managed code design and development, not just a straight port of typical C# code. You will likely be surprised by how your view of managed code changes as you start thinking in C++.

I’m really excited about Visual C++ 2005 for a few reasons:

It allows me to use and build on my investment in C++ while moving to managed code.

It is 100% backward compatible, allowing me to continue using the millions of lines of C and native C++ code that are in existence today along with managed code in a single component.

It provides a far more natural interop story than languages like C# allowing me to use existing header files, to call Windows API functions for example, without having to redefine all the structures and functions which can be error-prone.

It shows that C++ truly is an incredibly flexible language. The Visual C++ team was able to introduce CLR and GC constructs in a way that fits naturally into Standard C++ even if they are non-standard. Some people like to refer to this flexibility as the “complexity” of C++, but I think that this view is naïve. As other newer and “more elegant” languages evolve to introduce new language features and through necessity add new language constructs to solve various usage problems, the languages inevitably get more complex. As an example, avoiding things like declarator operators (such as *, & and ^ in C++) may simplify a language design for common code but does limit your options when greater flexibility is required. Nevertheless I love the fact that different languages are being developed as it provides inspiration for new language ideas for all language designers. VB, Java, C#, along with the countless languages that preceded them have introduced many interesting concepts to make the programmer’s life easier. C++/CLI is a testament to that by introducing (language, not library) features for concepts like garbage collection and useful and familiar constructs like the for each statement that have been around in other languages.

Here’s an excerpt from my evolving preface:

"C++ is a unique language in that it allows you to naturally program at different levels of abstraction. The level of abstraction you program at is up to you. What parts of the language you wish to make use of is also up to you. C++ doesn’t require you to understand every detail of the language and certainly you should not have to in order to be productive. You should always program at the highest level of abstraction that is possible and practical, but when the day comes that you need to go a little deeper to get something done, C++ will not stop you but instead will allow you to naturally extend your programming to a lower level of abstraction as needed."

Scoble has been fielding some questions about Longhorn’s .NET story. The bottom line is that building an operating system is a monumental task. With the amount of engineering gone into Windows it makes no sense to “rewrite” it in managed code. It does however make sense to provide managed wrappers for many of the OS services in the .NET Framework, as Microsoft has been doing, but we cannot expect that every last API will ever be completely wrapped by some managed abstraction. That’s where Visual C++ plays a significant role in allowing you to naturally mix native and managed code. You get the best of both worlds.

I wonder if Scoble would be interested in reading my book if I sent him a copy when it’s done…

That’s it for today. I know I’ve rambled a bit. Does this sound like something useful? I’d love to hear your feedback.


© 2005 Kenny Kerr

Posted by KennyKerr with 6 comment(s)

The Case of the Missing Generic (Parse Method)

I’ve noticed that quite a few people in the community have been wondering why on earth the System.Enum type in version 2 of the .NET Framework lacks a generic Parse method. If you haven’t used the Parse method lately, an example will help to clarify the frustration many developers have experienced.

I will use C# for this illustration since that is the language that causes much of the frustration.

:)

Here goes:

FileShare share1 = FileShare.Read | FileShare.Delete;
 
string text = share1.ToString();
Debug.Assert("Read, Delete" == text);
 
FileShare share2 = (FileShare) Enum.Parse(typeof(FileShare),
                                          text);
Debug.Assert(share1 == share2);

FileShare is an enum declared in the System.IO namespace. It defines the constraints placed on how a particular file can be shared. Since the CLR defines a common type system, FileShare ultimately derives from System.Object and inherits its virtual ToString method. In the example above, the share1 value is implicitly boxed and the ToString method is then dispatched against the boxed value. Since the FileShare type includes the Flags attribute, the ToString implementation provided by the abstract System.Enum value type knows to comma-separate the flags. Had the Flags attribute been omitted, the ToString override would simply have returned the string representation of the enum’s underlying type, typically a 32-bit integer. So far so good. It’s when you attempt to convert the string representation back to an enum value that the frustration begins.

To convert strings into enum values, the System.Enum type provides a static Parse method with the following signature, expressed in C#:

object Parse(Type enumType,
             string value,
             bool ignoreCase);

Since enums can have any underlying integral type, the Parse method cannot return a value type and thus returns an object. But what about returning System.Enum? There are two challenges with that. Firstly Enum is abstract so it cannot be returned by value and it’s abstract because Enum itself doesn’t contain the enum’s value field and returning it or passing it by value would slice away the value field. Secondly, C# doesn’t support strongly-typed boxed values – all boxed values are expressed as System.Object types in C#. C++/CLI allows you to express the Parse method more accurately:

Enum^ Parse(Type^ enumType,
            String^ value,
            bool ignoreCase);

If you’re not familiar with C++/CLI, the ^ declarator indicates that the type declaration is a handle to a CLR reference type. Enum^ is thus a handle to an Enum-derived value type. Unfortunately C# doesn’t support strongly-typed boxed values, but it would not help much anyway since an explicit conversion would still be required to convert the abstract Enum type to a concrete enum value. So let’s give up trying to improve on the respectable Parse method provided by the BCL and focus on how we might improve the situation from within the language.

Here is the Parse method usage again from the C# example:

FileShare share2 = (FileShare) Enum.Parse(typeof(FileShare),
                                          text);

There are fundamentally two problems with this code. The first is the need to repeatedly indicate the exact type of the enum we wish to convert to. A veteran C++ programmer might instinctively write the following (that is if the veteran C++ programmer were familiar with C++/CLI):

template <typename T>
T Parse(String^ value,
        bool ignoreCase = false)
{
    return safe_cast<T>(Enum::Parse(T::typeid,
                                    value,
                                    ignoreCase));
}

This solves the first problem nicely. The template function generates the necessary code to pass the type to the Parse method as well as to convert the result to the appropriate type. The typeid keyword returns the Type object for the type T. The safe_cast keyword unboxes the Object^ returned by the Parse method, converting it to the type indicated by the template type parameter.

With this template function available, the original C# example can be written more cleanly in C++ as follows:

FileShare share1 = FileShare::Read | FileShare::Delete;
 
String^ text = share1.ToString();
Debug::Assert("Read, Delete" == text);
 
FileShare share2 = Parse<FileShare>("Read, Delete");
Debug::Assert(share1 == share2);

This is certainly more elegant but there is still one more problem that plagues both the C# version as well as the C++ template version, although it’s less of a problem in C++. The issue is that we’re not using the compiler to perform any kind of validation to ensure that the types used with the Parse method are in fact of the correct type. In the C# example you can use two completely different types without as much as a warning from the compiler. The C++ example at least doesn’t allow that, but you can still use a non-enum type as the type parameter and the code will compile without any errors. This is less of a problem in practice since you will typically be assigning the result of the Parse method to a strongly-typed variable and the compiler will complain if the Parse template function’s calculated return type does not match the target of the assignment. Notice in this C# example that the wrong type is passed to the Parse method.

FileShare share2 = (FileShare) Enum.Parse(typeof(FileMode),
                                          text);

The template solution is adequate for C++, but can we do better? Why yes! There is even some hope for the C# programmer.

Templates use structural constraints when they are instantiated by the compiler. This is ideal for many classes of problems. In this case however we would like something a little different. What we need is a technique that provides subtype constraints. A CLR generic will do nicely. Consider the following generic C++ functions:

generic <typename T> where T : Enum
static T Parse(String^ value)
{
    return Parse<T>(value,
                    false);
}
 
generic <typename T> where T : Enum
static T Parse(String^ value,
               bool ignoreCase)
{
    return safe_cast<T>(Enum::Parse(T::typeid,
                                    value,
                                    ignoreCase));
}

By using a generic function, we can declare a subtype constraint for T such that the compiler will ensure that all uses of the Parse generic function are used with a type parameter that derives from Enum, thus only allowing CLR enumerated types. A default argument cannot be used as with the previous template function because default arguments are not allowed on generic functions or members of managed types. Default arguments are not supported by the CLR.

Finally, the question that may have popped into your head is why doesn’t the .NET Framework’s Enum class provide a generic Parse function as I have just described? The trouble is that C# doesn’t allow Enum to be used as a subtype constraint and the BCL is undoubtedly written in C#. Had the Visual C++ team been ready with C++/CLI when .NET was first being hatched, I suspect things might have turned out differently. Fortunately C++/CLI is coming soon in Visual C++ 2005 and brings all the power and flexibility of templates, generics and multi-paradigm programming to the .NET Framework.

If you’re a C# programmer and aren’t ready to switch to C++ then not to work. Although C# doesn’t allow you to declare the generic function equivalent to the C++ example above, the good news is that Visual C++ generates perfectly legal CLI metadata and IL. Simply expose the generic Parse method on a public class in a C++ library assembly and reference it from your C# project. Using it is simple and natural in C#:

FileShare share2 = Utility.Parse<FileShare>(text);

Don’t you just love .NET! Happy coding, whatever your language(s) of choice.


© 2005 Kenny Kerr

Posted by KennyKerr with 1 comment(s)
More Posts