C# Blooper №3: No warnings about fields having already been initialized

Before reading any further, please read the disclaimer in the C# Bloopers post.

When you declare a member variable and you pre-initialize it at the same time, and then you try to re-initialize it within the constructor without ever making use of its original pre-initialized value, you receive no warning about the field having already been initialized.

namespace Test3 
{  
    public class Test 
    {  
        public readonly string m = "m"; 
        public string n = "n"; 
        private string o = "o"; 
        protected readonly string p = "p"; 
        protected string q = "p"; 
        private string r = "r"; 

        Test() 
        {  
            m = "m2"; //Blooper: no warning about field having already been initialized. 
            n = "n2"; //Blooper: no warning about field having already been initialized. 
            o = "o2"; //Blooper: no warning about field having already been initialized. 
            p = "p2"; //Blooper: no warning about field having already been initialized. 
            q = "q2"; //Blooper: no warning about field having already been initialized. 
            r = "r2"; //Blooper: no warning about field having already been initialized. 
            o.ToLower(); //to prevent Warning CS0414: The field is assigned but its value is never used. 
            r.ToLower(); //to prevent Warning CS0414: The field is assigned but its value is never used. 
        }  
    } 
}  

This means that you may accidentally invoke complex initialization logic twice, unnecessarily wasting memory and clock cycles, and it may also lead to logic errors, if by any chance that initialization logic has side effects which are only meant to occur once. It may also confuse someone reading your code, (or even yourself looking at your code months later,) trying to figure out what's the purpose behind the seemingly repeated initialization, before the realization sinks in that it is simply redundant. Furthermore, if the re-initialization happens to differ from the pre-initialization, a good question arises, asking which one of the two was meant to be the correct one.

Read more »

C# Blooper №2: No warnings about accessing uninitialized members

Before reading any further, please read the disclaimer in the C# Bloopers post.

When you declare a member variable, and then you try to read it from within the constructor without having first initialized it, you receive no warning about accessing an uninitialized member. This happens even if the member is declared as readonly.

namespace Test2  
{  
    public class Test 
    {  
        public readonly string m; 
        public string n; 
        protected readonly string o; 
        protected string p; 
        private readonly string q; 
        private string r; 

        Test() 
        {  
            m.ToUpper(); //Blooper: no warning about accessing uninitialized member. 
            n.ToUpper(); //Blooper: no warning about accessing uninitialized member. 
            o.ToUpper(); //Blooper: no warning about accessing uninitialized member. 
            p.ToUpper(); //Blooper: no warning about accessing uninitialized member. 
            q.ToUpper(); //Blooper: no warning about accessing uninitialized member. 
            r.ToUpper(); //Blooper: no warning about accessing uninitialized member. 
            q = "q"; //to prevent Warning CS0649: Field is never assigned to, and will always have its default value null 
            r = "r"; //to prevent Warning CS0649: Field is never assigned to, and will always have its default value null 
        }  
    } 
}  

Someone might argue that this is behavior is fine because the member in question is guaranteed to contain its default value. First of all, a readonly member containing its default value is completely useless. (See C# Blooper №1: No warnings about uninitialized readonly members) Secondly, if the compiler is to help the developer catch potential errors and write better code, this is not a valid excuse: a different strategy is necessary.

Read more »

C# Bloopers

Please do not get me wrong; C# is awesome. It is the language of my choice, even though I am pretty well versed in C++ and Java. That having been said, it cannot be denied that C# has its share of flaws, too. In this series of posts I am documenting some of them, in no particular order.

Also please note that some of the issues described here are Visual Studio bloopers, or DotNet bloopers, and not C#-in-general bloopers.

Read more »

Hail-Mary Initialization

Introduction

Hail Mary Initialization is the cargo cult programming practice of pre-initializing a local variable with some default value, "just in case", even though that value will subsequently be overwritten in all code paths before it will ever be read. It is commonly done under the impression that it reduces the chances of error, but in reality it achieves the exact opposite: it increases the chances of error.

Read more »

C# Blooper №1: No warnings about uninitialized readonly members

(When the class is public and the member is public, protected or protected internal.)

Before reading any further, please read the disclaimer in the C# Bloopers post.

The C# compiler is kind enough to give you a "field is never assigned to" warning if you forget to initialize a readonly member which is private or internal, or if the class in which it is being declared is internal. But if the class is public, and the readonly member is public, protected or protected internal, then no warning for you! Why, oh why?

Read more »

Intertwine: Normalizing Interface Invocations

Note: This post has been superseded by a new post in 2022. See Intertwine.

This is a C# project that I did back in 2011. It consists of a (rather informal) white paper which describes the project, and a zip file containing the source code in the form of a Microsoft Visual Studio solution.

Here is the abstract:

A mechanism is proposed for converting (entwining) method call invocations of any interface to a general purpose single-method normal form, and converting back (untwining) from the normal form to interface invocations, so that operations can be performed on the normal form in a way agnostic to the interface being invoked. The normal form is a delegate in C# or a functional interface in Java, realized as object AnyCall( int selector, object[] parameters ). A DotNet implementation is provided in C#, though the discussion also applies to Java.

Read more »