A Beginner’s Tutorial on Extension Methods, Named Parameters, Optional Parameters, Object Initializers and Anonymous types in C#

In this article we will discuss four very important features of C# programming language. These new features are introduced in the later versions of C# and developers coming from the older version like C# 2.0 or perhaps learning C# might find this article useful.

Background

C# is a languages that is improving at a very fast pace. It is getting more and more features with every release. It came years after the languages like C++ and Java but managed to surpass them in terms of language features and developer productivity.

In this small tutorial article, I will try to explain four very important features of C# programming language in my own way. This might not be very useful for those who are already aware of these features but this article could be useful for the beginner’s who are still in the phase of learning C#.

We will be discussing following four features of C# in this article. We will also write sample application for each to see them in action.

  • Extension Methods
  • Named and Optional Parameters
  • Object Initializers
  • Anonymous types

Using the code

Extension Methods

Open Closed Principle(OCP)states that we should design our types in such a way that it should be open for extension but closed for modification. Extension methods in C# can be thought of as a mechanism to implement the OCPfor user defined types or even the primitive types and the types defined in the framework.

Extension methods allow us to extend an existing type by adding additional methods and functionality to an existing type without needing to change the code of that type(we might even not have code in most cases). Prior to the existence of extension methods, developers used to create their own types and either inherit or contain the existing type inside these types. These new types were more of the wrapperson the existing types rather than the actual extensions of these types.

For example  if we needed to have the functionality of getting the negative of an integer then I will have to wrap my integer in a custom type and then use this custom type to perform the operation.

Now this approach did work but the problem is that we are not at all extending the existing type. We are creating a new type all together that is wrapping the existing type and then providing us the desired functionality.

So if we really want to extend a method we should be able to add this method Negatein the int type only and everyone should be able to call this method on inttype only. No need to create another type to have this additional functionality. Extension methods provides just the same thing. Using extension methods we can write the custom functionality and can hook them with the existing types so that they can be used on those types.

To create an extension method, we need to take the following steps:

  1. Define a staticclass.
  2. Define a public static function in this class with the name desired as the mew method name and return value as per the functionality.
  3. Pass the parameter of type that you want to extend. The important thing here is to put a thiskeyword before the parameter to tell the compiler that we need to extend this type and we are not really expecting this type as argument.

So lets try to add this Negatefunction in the int type.

Now using extension method let us define the methods on some existing type. Now what if we want the new method to accept some parameters. Well to do this we can define additional parameters after the first parameter that is of the type to be extended (used with this keyword . Let define one more function in intcalled Multiplyto see this in action.

Now there are two points that need to be remembered before implementing extension methods.

  • First of which is that the extension methods can only access the publicproperties of the type.
  • The extension method signature should not be same as an existing method of the type.
  • The extension method for a type can only be used if the namespace that contains the extension method is in scope.
  • In case we define extension methods in such a way that it overloads an existing method of the original type and the calls are getting ambiguous then the overload resolution rule will always choose the instance method over the extension method.
  • If there is some ambiguity between two extension methods then the method containing more specific arguments will get called.

If we keep the following point in mind we could really utilize the extension methods to better design and extend the types and provide better abstraction of the type. LINQuses extension methods heavily. It is highly recommended to look at how LINQused extension methods in conjunction with LAMBDAexpression.

Note: Information on Lambda expressions can be found here: A Beginner’s Tutorial on Basics of Delegates, Anonymous Functions and Lambda Expressions in C#[^]

Optional Parameters

Now before we go ahead and start talking about Named and positional parameters let us talk a little about optional parameters. In older versions of C#, it was not possible to create optional parameters for functions. i.e. If I need to have default value of a parameter in a function the only way to do that was the function overloading.

Lets say we want to define a function Multiply in which the the caller can pass two numbers and get the result back. But if the user wants to pass only one parameter than that is allowed too and the function will Multiply this number with 1 and return the value. Now in older versions of C#, this is done using function overloading as:

Now this provided the desired result but the problem here is that as the number of function arguments increase the number of overloaded functions will also increase to provide all possible combinations. Having a lot of overloaded version of function is a maintenance nightmare.

Now to solve this problem C# introduced the provision of having optional parameters in functions. So using optional parameters the above function will look like:

The only limitation of having optional parameters is that the default parameters should always come after all the mandatory parameters in a function.

Named Parameters

Now having the possibility of having the optional parameter is great but there is one small problem, if we have multiple optional parameters in a function. Lets say we have a function like this:

Now we want to pass the values of fourand fivebut want to use the default value of three. This would not be possible under normal conditions. To perform this operation we need to use the named parameters. named parameters gives us the possibility of passing specific function argument with their names. So lets try to call this function.

Now calling the function like above we use the default value of threeand at the same time pass the values for fourand five, which are the optional parameters defined after three.

We have also used the named argument for variable oneand two. but since we are passing oneand twoat their respective parameter positions we can omit the names from them and thus they will simply be passed as positional parameters and fourand fiveas named parameters.

Object Initializers

Object initializers in C# provides us with a simple way to initialize all the properties of objects at the time of construction only. Lets say we have a simple class with some public properties as:

Now let us create the object of this class using object initializers as:

A note on Automatic Properties

Now the way I defined the class properties might be new for the the guys using C# 2.0 or below. The properties are defined as automatic properties. If any variable of our class is only acting as a data store and has no validation logic before setting or getting it then we can completely skip the creation of the variable and directly create the property. The compiler will take care of generating a variable for this property at run-time.

Implicitly Typed Variables and Anonymous Types

In C# 3.0 and above, we can define a variable without specifying its actual type provided that the variable is being assigned with some value. These variables are implicitly type i.e. the type of the variable is the type of the variable that is being assigned to it.

Now the type of the var1is Dictionary<string, Book> because it is being created as that. The type of var2is stringbecause a string is being assigned to it and type of var3is intbecause the function is returning a int.

vardoes not define a dynamic variable that can be assigned with any type. It is just a syntactic sugar so that we can skip defining the type of variable in local scope.

varis just a syntactic sugar, Having said that, there is one more thing that is important. We should try not to use the varkeyword for declaring local variables because for which we can define explicit types. The reason for this is that it reduced readability of code. Now the question would be when to use var?

We should use var only when we have to. The only place we need to use varis with Anonymous types i.e. types that are created on the fly and their type name is not available at compile time. LINQqueries often creates the need of creating Anonymous types and this is the only place we should use implicitly types variable i.e. var.

Let us create a simple anonymous type, assign it and use it using implicitly typed variable.

Note: Anonymous type mandates the use of varkeyword. for all other scenarios it is not recommended to use varbecause of the above mentioned reduced readability problem. if LINQprojections are being used then the use of varkeyword is an absolute must.

Point of interest

In this article we talked about some features of C# that were introduced in C# 3.0. This article is meant for the absolute beginner’s who are not aware of these features of C# and is written from absolute beginner’s perspective only. I highly recommend looking at the code to get the full understanding of all these features. I hope this has been informative.

Download sample code for this article: CSharpTutorialSampleApp