Language Feature Highlight: Local Type Inference in C# 3.0 and Visual Basic 9.0

Welcome to this installment of the .NET Nuts & Bolts column. The focus of this article will be on highlighting the local type inference feature that has been added to C# 3.0 and Visual Basic 9.0 languages. You'll touch on what it is, the syntax behind it, and why it is relevant to understand. You'll also touch on some examples of invalid uses because it can be just as helpful to examine what it is not to get a grasp on the concept.

Local Type Inference Defined

Local type inference is a language feature that allows you to define variables and use them without worrying about their true type. Local type inference is also interchangeably known as implicitly typed local variables. The burden is put on the respective language compiler to determine the type of a variable by inferring it from the expression assigned to the variable. The result is type safety while allowing you to write more relaxed code, which is required to support Language Integrated Query (LINQ).

Based on the description and a first glance of code, it is very easy to mistake type inference to be similar to defining everything as a type object or use of variants, which is heavily used in Visual Basic 6.0. This is entirely untrue and not what type inference is about. Type inferred variables are strongly typed. The type cannot be changed once it is assigned as could be done with a variant type so it does not involve any casting operations or the resulting performance implications. A strong type is assigned, but simply done so by the compiler based on the results of the expression assigned to the variable. The net effect is the true type isn't as readily apparent when reading code, but the Visual Studio IDE will tell you the type assigned along with the GetType() method will return a strong type at runtime.

There may be temptation over time to get lazy and let the compiler do the work for you by using type inference across the board. However, this is where the local part of local type inference comes into play. Type inference can only be used within a local scope where its type can be inferred by the expression assignment. Type inference cannot be applied to any of the following:

  • Cannot be a part of a member property declaration on a class, struct, or interface
  • Cannot be used in a parameter list on a method
  • Cannot be a return type for a method
  • Cannot be defined without a right hand assignment expression
  • Cannot reassign to be a different type once type has been inferred

Local Type Inference in C# 3.0

C# 3.0 implements local type inference through the var keyword in place of a specific type in a variable declaration.

The sample code below demonstrates the syntax for local type inference in C#. I created a new Windows console project to hold the code. Visual Studio 2008 Beta 2 was used to create the examples contained within.

namespace CodeGuru.TypeInference
{
   class Program
   {
      static void Main(string[] args)
      {
         int a = 5;
         var b = a;           // int
         var x = 5.5M;        // double
         var s = "string";    // string
         var l = s.Length;    // int

         Console.WriteLine("value of b is {0} and type is {1}",
            b, b.GetType().ToString());
         Console.WriteLine("type of x is {0}", x.GetType().ToString());
         Console.WriteLine("type of s is {0}", s.GetType().ToString());
         Console.WriteLine("type of l is {0}", l.GetType().ToString());

         Console.ReadLine();
      }
   }
)

It can be just as useful at times to look at examples where something does not apply. The following sample C# code demonstrates situations in which local type inference cannot be used. The code that is listed below will result in six different compile errors based on invalid usage and intentionally will not compile.

namespace CodeGuru.TypeInference
{
   class Program
   {
      var test = "invalid use";    // invalid in member declaration

      // Invalid as parameter
      public void TryAsParameter(var parm)
      {
      }

      // Invalid as return type
      public var TryAsReturnType()
      {
         return "invalid use";
      }

      public void TryInvalidLocalUse()
      {
         var local1;                // must be initialized
         var local2 = null;         // can't infer type from null

         var local3 = 5;            // valid use
         local3 = "change type";    // can't change type
      }
   }
}

Local Type Inference in Visual Basic 9.0

Using local type inference in Visual Basic is more likely to be misleading because it can appear as if it matches the behavior of Option Strict Off. As with C#, you still get a strong type despite the appearances. The syntax in Visual Basic is to omit the As Type part of the variable declaration. This will work just fine with Option Strict On and it is encouraged to continue use of Option Strict On to ensure variant types are not allowed and avoids the undesired boxing and unboxing.

Visual Basic allows you to turn local type inference on and off. There is Option Infer On and Option Infer Off that will enable or disable local type inference respectively. It is on by default.

The sample code below will demonstrate the syntax for local type inference in Visual Basic.

Option Strict On

Module Module1

   Sub Main()

      Dim As Integer = 5
      Dim b = a             ' int
      Dim x = 5.5           ' double
      Dim s = "string"      ' string
      Dim l = s.Length()    ' int

      Console.WriteLine("value of b is {0} and type is {1}", b, _
         b.GetType().ToString())
      Console.WriteLine("type of x is {0}", x.GetType().ToString())
      Console.WriteLine("type of s is {0}", s.GetType().ToString())
      Console.WriteLine("type of l is {0}", l.GetType().ToString())

      Console.ReadLine()

   End Sub

End Module

As with the C# example, it can be just as beneficial to demonstrate where local type inference cannot be used. The following sample code demonstrates invalid attempts at using local type inference in Visual Basic 9.0. It is important to note this code will not compile.

Module Module1

   Dim test = "invalid use"    ' invalid in member declaration

   ' Invalid as parameter
   Sub TryAsParameter(ByVal parm)
   End Sub


   Sub Main()
      Dim local                 ' must be initialized

      Dim local3 = 5            ' valid use
      local3 = "change type"    ' cannot change type
   End Sub

End Module

Summary

This article covered the local type inference language feature. You examined what it is along with the syntax using examples of how it can and cannot be used. Type inference is one of the language features along with extension methods, partial methods, and others that enable Language Integrated Queries (LINQ) to be possible, so it is important to understand how type inference works and what it is not.

Future Columns

The topic of the next column is yet to be determined. It is likely I will cover another upcoming language feature. If you have something in particular that you would like to see explained here, you could reach me at mstrawmyer@crowechizek.com.



About the Author

Mark Strawmyer

Mark Strawmyer is a Senior Architect of .NET applications for large and mid-size organizations. He specializes in architecture, design and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the fifth year in a row. You can reach Mark at mark.strawmyer@crowehorwath.com.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds