In the last few days I spent some time trying to unify structure of one of the project I`m currently working on. Most of the changes were about changing variable types because it`s were not used right way. That is why in this post I want to share my observations and practices with you.
First of all we need to understand what 'variable definition' is and how it`s different from 'variable initialization'. This part should be pretty straightforward:
- variable definition consist of data type and variable name only <data_type> <variable_name>; for example int i; . It`s important to understand how variable definition affects your code because it behaves differently depends weather you work with value or reference types. In the case of value types after defining variable it always has default value and it`s never null value. However after defined reference type variable without initializing it has null value by default.
- variable initialization is a process of assigning value to the variable - variable_name = value; it can be merged with the definition into one line expression <data_type> <variable_name> = value;
Code Snippet
- public class Test
- {
- public Test()
- {
- // variable definition for value type.
- int i; // i == 0 as this stage.
- // variable definition for reference type.
- string s; // s == null at this stage.
- // value type variable initialization
- i = 10; // i == 10.
- // referece type variable initialization
- s = "Test";
- }
- }
Now we can go forward and compare a different types of a variable definition. As many of you remember in the past, in .NET Framework 2.0, only one type of variable definition exists. Here I mean classic, strongly typed, combination of type and variable name (example below line 13.). It was very popular (because at this time there was nothing else to replace it) but this approach requires creating separated type for each problem. This cause in many project multiple very similar types exists so it was not a perfect solution.
Code Snippet
- public class Test
- {
- public class SomeType
- {
- internal void DoSomething()
- {
- }
- }
- public Test()
- {
- SomeType type = new SomeType();
- type.DoSomething();
- }
- }
Since .NET Framework 3.0 developers was able to switch their mind into different kind of thinking about defining variables because a new var keyword became in use. A var keyword is separated type of defining variables, which are still strongly typed but it`s resolved by the compiler based on value assigned to it during initialization (a var variable have to be defined and initialized in the same line of code). Why is so cool to use it? This is a very good question and a lot discussions around that already exists in the Internet. First of all variables defined with var keyword in general have more descriptive name because in other case even developer might have a problem with reading own code. Let see an example:
Code Snippet
- using System.Collections.Generic;
- public class Test
- {
- public class SomeType
- {
- internal void DoSomething()
- {
- }
- }
- public Test()
- {
- // SomeType someType = new SomeType();
- var someType = new SomeType(); // equivalent to line above.
- var someTypeList= new List<SomeType>();
- }
- }
However the real power of using var keyword ins`t naming convention but something which is called anonymous types. It`s really powerful tool in developers hands!! Anonymous types are generated by the compiler, are strongly typed and not exists physically as a class or structure in a project code but provide a convenient way to encapsulate a set of read-only properties into a single object. Let`s see example of using it:
Code Snippet
- using System.Collections.Generic;
- using System.Linq;
- using System;
- public class Test
- {
- public class User
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public string Surname { get; set; }
- public string Department { get; set; }
- public byte[] HugeArray { get; set; }
- }
- public Test()
- {
- var userList = new List<User>();
- // code to populate the list.
- // Creating a new anonymous type with HrId and FullName properties.
- var userInHrDepartment = from user in userList
- where user.Department == "HR"
- select new { HrId = user.Id, FullName = user.Name + " " + user.Surname };
- // Tterate through collection of anonymous type.
- foreach (var hrUser in userInHrDepartment)
- {
- Console.WriteLine(hrUser.FullName);
- }
- }
- }
As you can see by using a very simple LINQ query I`m extracting only variable I really want to process, and without creating strong type explicit I`m using anonymous type to iterate through the collection and accessing specific properties.
Last type of a variable definitions comes with .NET Framework 4.0 which introduce a new dynamic type.
This is completely different type of thinking for developers because this type of object behaves very similar to the well know object type. However the difference between those two is huge because object is so powerful because of inheritance while dynamic type is not strongly typed, late-bound and exists only at run-time. Basically it`s a bag where we can put everything and expect everything but we can`t be sure that something exist there. Let see dynamic type in action.
Code Snippet
- using System.Collections.Generic;
- using System.Linq;
- using System;
- public class Test
- {
- public class User
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public string Surname { get; set; }
- public string Department { get; set; }
- public byte[] HugeArray { get; set; }
- }
- public Test()
- {
- var user = new User();
- dynamic userModyfied = user;
- // Adding extra property to the User type.
- userModyfied.AdditionalProperty = "Test value";
- Console.WriteLine(userModyfied.AdditionalProperty);
- dynamic userModyfied2 = new User();
- userModyfied2.AdditionalProperty2 = "Test value 2";
- Console.WriteLine(userModyfied.AdditionalProperty2); // value exists
- Console.WriteLine(userModyfied.AdditionalProperty); // value doesn`t exist
- }
- }
As you can see in the example above. This is very strange type and might bring a lot or troubles when used incorrectly. Additionally usage it hurts performance of our solution so use it wisely only if necessary.
Thank you