Categories
Software Development Visual Basic.NET

Is IIF part of the VB.NET language?

The answer is NO. Does it feel like it is part of the language, YES.

When coding in Visual Basic.NET you’ll come across three variations of an “IF”.

  • IIF Function
  • IF() Operator
  • IF…Then…Else Statement

The IF() operator and the IF…Then…Else Statement are part of the VB.NET Language.

The IIF Function is not, even though you can use it. These three features operate differently and have different purposes, this post isn’t meant to get into those differences, but will discuss how IIF() and IF() are defined and used by the compiler. Most likely when you are using the IIF Function, you probably want to be using the IF() Operator.

The IIF function is imported by default due to the VB Compiler Response file that is included when the compiler is installed. The VB Compiler Response file includes a line which makes this possible:

/imports:Microsoft.VisualBasic

The Microsoft.VisualBasic.dll is always referenced by the compiler regardless of what command line options you specify.

Which is why compiling this code will work, even though IIF is NOT part of the Visual Basic .NET language.

Module Module1

    Sub Main()

        Console.WriteLine(IIf(True, "Hi Mark", "Hi Tom"))


    End Sub

End Module

Which is successfully compiled with this command

vbc ExampleModule.vb

However, if you were to enter this command

vbc /noconfig ExampleModule.vb

You would be presented with the following errors:

error BC30451: 'Console' is not declared. It may be inaccessible due to its protection level.

        Console.WriteLine(IIf(True, "Hi Mark", "Hi Tom"))
        ~~~~~~~

error BC30451: 'IIf' is not declared. It may be inaccessible due to its protection level.

        Console.WriteLine(IIf(True, "Hi Mark", "Hi Tom"))
                          ~~~

There are two errors, because /noconfig caused the vb compiler to not load the compiler responses file, which means neither System or Microsoft.VisualBasic were imported by default.

If we modify our code above, to include these imports, it will now compile with /noconfig

Imports System
Imports Microsoft.VisualBasic

Module Module1
    Sub Main()
        Console.WriteLine(IIf(True, "Hi Mark", "Hi Tom"))
    End Sub
End Module

This will compile with the /noconfig flag. Since there isn’t any reason to make our lives harder we typically wouldn’t run VBC with the /noconfig (although Visual Studio does, but at least there it deals with specificying all the required parameters.)

If IIF isn’t part of the Language where does it come from?

Inside the Microsoft.VisualBasic.dll there is a Module named Interactions which defines the globally scoped function IIF

public static object IIf (bool Expression, object TruePart, object FalsePart);

Due to Microsoft.VisualBasic.dll being referenced by the compiler intrinsically and the Import of the Microsoft.VisualBasic namespace by the compiler responses file (in the case of a Visual Studio project it’s specified in the build file,) the IIF function is available for use automatically.

Why is the IIF Function there when we have the IF() Operator?

I don’t have a first hand answer from any decision makers involved in drafting the Visual Basic Language specification, so this answer is part research, intuition, and speculation.

From 2002 to 2008, the Visual Basic.NET language didn’t offer the IF() Operator. Prior to Visual Basic.NET, Basic and Visual Basic programmers had access to an IIF function in many other languages, like VBA, FoxPro, and T-SQL. I believe I remember using it in versions of Basic and Visual Basic, but can’t find any supporting documentation.

In addition to retaining the functionality programmers were used to; adding it to Visual Basic.NET with similar behavior to what existed prior likely made upgrading old basic systems to VB.NET an easier process.

In 2008, with Visual Basic .NET 9.0 the IF() operator was introduced. Also bringing forward the wave of new advice and discussions of using “IF() instead of IIF()”

If IIF is not part of the language, then what is it?

Ok, so strictly speaking, it’s not a feature of the Visual Basic.NET language. On the other hand if you create a Code.vb txt file and compile it, by default IIF is a feature available to you. Which is also true when creating a new project in Visual Studio. I’d call it a Framework feature that is available to VB code files by default.

If IIF is a framework feature, can we use it from C#?

Let’s give it a try, we’ll start with this code

namespace ExampleIfInCSharp
{
    using System;
    using Microsoft.VisualBasic;

    public class Program
    {
        public static int Main(string[] args)
        {
            // Framework Feature IIF, in Microsoft.VisualBasic
            Console.WriteLine(IIF(true, "Hi Mark", "Hi Tom"));
            Console.WriteLine(IIF(false, "Hi Mark", "Hi Tom"));

            // C# Language Feature - Ternary Operator
            Console.WriteLine(true ? "Hi Mark" : "Hi Tom");

            // VB.NET Language Feature - IF() Operator
            //    this won't compile with C# 
            Console.WriteLine(IF(true, "Hi Mark", "Hi Tom"));

            return 0;
        }
    }
}

Now let’s try to compile that

csc iif-in-csharp.cs
Microsoft (R) Visual C# Compiler version 3.10.0-4.21318.11 (7ceb6331)
Copyright (C) Microsoft Corporation. All rights reserved.

iif-in-csharp.cs(11,31): error CS0103: The name 'IIF' does not exist in the current context
iif-in-csharp.cs(12,31): error CS0103: The name 'IIF' does not exist in the current context
iif-in-csharp.cs(19,31): error CS0103: The name 'IF' does not exist in the current context

We see that the compile does not like IF or IIF. Above we discovered that IIF requires a reference to the Microsoft.VisualBasic.dll which happens automatically with the VB Compiler, and that the VB Compiler Responses file automatically Imports the Microsoft.VisualBasic namespace.

Let’s take this a step further, our code already has a using importing the Microsoft.VisualBasic namespace. Let’s add a reference to Microsoft.VisualBasic.dll and compile:

csc /r:Microsoft.VisualBasic.dll iif-in-csharp.cs
Microsoft (R) Visual C# Compiler version 3.10.0-4.21318.11 (7ceb6331)
Copyright (C) Microsoft Corporation. All rights reserved.

iif-in-csharp.cs(11,31): error CS0103: The name 'IIF' does not exist in the current context
iif-in-csharp.cs(12,31): error CS0103: The name 'IIF' does not exist in the current context
iif-in-csharp.cs(19,31): error CS0103: The name 'IF' does not exist in the current context

What is interesting here, is that we now have a reference to Microsoft.VisualBasic.dll and a using for Microsoft.VisualBasic in our code. The code hasn’t changed from above, all we changed was command we were using to compile our code. We still have all of the same errors though.

C# is different from VB.NET; it has different language features. A feature of C# is that it’s case sensitive, while VB.NET is case-insensitive. Also VB.NET supports global modules as a feature while C# does not support modules. I think we have to make a few more code changes:

We are going to change the casing of IIF to IIf, and prefix it with the module name Interaction.

namespace ExampleIfInCSharp
{
    using System;
    using Microsoft.VisualBasic;

    public class Program
    {
        public static int Main(string[] args)
        {
            // Framework Feature IIF, in Microsoft.VisualBasic
            Console.WriteLine(Interaction.IIf(true, "Hi Mark", "Hi Tom"));
            Console.WriteLine(Interaction.IIf(false, "Hi Mark", "Hi Tom"));

            // C# Language Feature - Ternary Operator
            Console.WriteLine(true ? "Hi Mark" : "Hi Tom");

            // VB.NET Language Feature - IF() Operator
            //    this won't compile with C# 
            Console.WriteLine(IF(true, "Hi Mark", "Hi Tom"));

            return 0;
        }
    }
}

Now we’ll compile this and see what happens:

csc /r:Microsoft.VisualBasic.dll iif-in-csharp.cs
Microsoft (R) Visual C# Compiler version 3.10.0-4.21318.11 (7ceb6331)
Copyright (C) Microsoft Corporation. All rights reserved.

iif-in-csharp.cs(19,31): error CS0103: The name 'IF' does not exist in the current context

Progress! We have IIf working in our c# code, but we still have the problem with the IF() operator. Our only choice is to remove this from our code, or create our own function named If(), but we would never do this, because the C# ternary operator (?:) does the same thing, and adding an If() function would create confusion. Additionally writing an IF() function in C# would still not behave like the IF() operator in VB, it would behave just like the IIF function.

The IF() operator can not be used directly in C# because of where it’s defined. It’s a language feature, meaning it’s specified in the “grammar” of what makes a Visual Basic.NET program. There isn’t a way to tell the CSharp compiler that it should refer to the Visual Basic.NET Grammar, which makes a lot of sense. This would be like trying to convince your swim teacher that a basketball is required for swimming. Clearly a basketball is not a tool in a swimmer’s toolbox. Just as the CSC compiler wouldn’t consider IF() as tool that could be used by a programmer in a C# program.

The IIF function is available to C# and VB.NET because it’s part of the “Framework.” It was coded in some language, which is irrelevant, and it was compiled into a .NET assembly, therefore .NET Applications can reference that assembly and use the publicly exposed types in it.

Here is our final program in C#

namespace ExampleIfInCSharp
{
    using System;
    using Microsoft.VisualBasic;

    public class Program
    {
        public static int Main(string[] args)
        {
            // Framework Feature IIF, in Microsoft.VisualBasic
            Console.WriteLine(Interaction.IIf(true, "Hi Mark", "Hi Tom"));
            Console.WriteLine(Interaction.IIf(false, "Hi Mark", "Hi Tom"));

            // C# Language Feature - Ternary Operator
            Console.WriteLine(true ? "Hi Mark" : "Hi Tom");

            // VB.NET Language Feature - IF() Operator
            //    this won't compile with C# 
            //Console.WriteLine(IF(true, "Hi Mark", "Hi Tom"));

            return 0;
        }
    }
}

And when we compile, Voila! No errors.

csc /r:Microsoft.VisualBasic.dll iif-in-csharp.cs
Microsoft (R) Visual C# Compiler version 3.10.0-4.21318.11 (7ceb6331)
Copyright (C) Microsoft Corporation. All rights reserved.

In conclusion, we can use framework features in any language, although you can see in this case how Microsoft made it difficult to use this in C# but not impossible. This is probably intentional since using IIf in C# wouldn’t add any value to a C# program. Today most would argue that IIf doesn’t add any value to a VB.NET program either, unless you had a very specific need for a confusing line of code that represented logic branching in an IF-like structure but didn’t have short-circuiting.