Marking Methods “Obsolete” In C# Class Library

Note: For my all articles on C#.Net / Visual Studio, please visit here.

The following are the objectives of this article:

  • What’s an obsolete method?
  • Why & when should a method be marked as obsolete?
  • Available options in C#

What’s an obsolete method?

A method in a class library which is old or out-of-use and some other method instead of this is suggested to be used.

Generally, when you are introducing some new functionality in your class library but still want to keep an old method intact for some time until the next big release then it’s better to mark that old method as “Obsolete” and offer new functionality in a new method.

Why & when should a method be marked as obsolete?

You are introducing some changes in your class library, and replacing a method with a new one with some added features, at that time it is a good idea to not suddenly remove that method from your class library because it may break some code. But if you mark that method as obsolete then it is an indication that this method is already out-of-use and something else should be used in its place.

Available options in C#

Let’s now see what options are available in C# to mark a method as obsolete.

Open Visual Studio 2015 or 2017 and create a C# class library project named “TestClassLibrary”:


Add a new static class in that project names “TestClass”. Add the following method in that class,

public static string ToUpper(string input) {  
    return input.ToUpper();  

Now right click on solution and add a new console application project named “TestConsoleApplication”.


Add reference of class library project in console application project,


Go to the Program.cs class and add following “using” statement at top,

using TestClassLibrary;

Go to the “Main” method and add following code

Console.WriteLine(TestClass.ToUpper("test input"));  


Build the solution by pressing F6 and it should build fine without any error or warning.

Now, let’s go to the TestClass and mark the ToUpper method as obsolete. For that just add “[Obsolete()]” attribute above the ToUpper method.

The whole TestClass.cs will look like this,


What have we done here?

We have marked the method with “Obsolete” attribute indicating its users that this method is now deprecated and will be removed in future release. So, it’s advisable not to use it.

If you go to the console application, then you will see a green line below the code where this method is called, if you move your mouse over that green line you will see the warning message,


If you build the project and then see error list window, you will see a warning,


Note here the warning code CS0612. It’s a compiler warning code. If you click on the link CS0612, then you will see Microsoft documentation for this code will open in your browser,


But this does not look like a good direction to the programmers on what to use if not this method.

Let’s add one more method to class library.

Go to TestClass.cs in class library project and add following method which has better error handling and its culture-neutral.

public static string MakeUpperCase(string input) {  
    if (String.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input));  

    return input.ToUpperInvariant();

Now we want to indicate to the programmers that instead of “ToUpper” method, they should use “MakeUpperCase” method. Add a message inside “Obsolete” attribute on top of “ToUpper” method:

[Obsolete("This method should not be used, Use MakeUpperCase instead.")]

The whole method will look like,


What have we done here?

We have marked the method with “Obsolete” attribute and added a message to be shown to the user which can work as an indicator to use some other replacement method.

If you now build the project and go to the Main method, you will see a warning with the above message,


Now this looks like a good direction to a programmer who is going to use your class library.

Later, if you think that you have given enough warning and time to programmers using your class library that they should not use this method, and you want to raise an error if they do, then you can convert this warning into error by passing “true” Boolean value after the message:

[Obsolete("This method should not be used, Use MakeUpperCase instead.", true)]

The whole method will look like this,


What have we done here?

We have marked the method with “Obsolete” attribute and added a flag indicating compiler should raise an error if this method is used somewhere.

If you build your project now, it will throw an error,


Use this error flag in your class library when you want to introduce breaking changes in code.

In summary, we have seen the following three overloads of “Obsolete” attribute,


I have attached a sample project with this article, downloaded it and built it one by one by un-commenting only one “Obsolete” attribute at a time,


Note: This article was originally published by me on C# Corner website here.

C# Digit Separator

Note: For all my articles on C#.Net / Visual Studio, please visit here.


Sometimes, when you want to represent a big integer or long literal in C# code, it becomes less readable and there are chances to misspell a digit too.

Consider the following example of a C# constant,

const int assumedPopulation = 1122339654;
You will find the one line code is neat and clean, but the numeric value/literal is not so readable.

It would be better if there was some digit separator like we have in Excel for numbers. Then, the number would be easy to read, like below.


With C# 7, Microsoft has introduced a digit separator. While it’s not the regular digit separator “comma” which we use everywhere, it’s underscore.

In C# 7, the same line of code can be written as,

const int assumedPopulation = 1_122_339_654;
Doesn’t it make the number quite easily readable?
And this digit separator does not affect its display on UI.

Write the following code in a C# 7 console app (With VS 2017), and check the output on the console. The digit separator will not be printed on console.

static void Main(string[] args)  
   const int assumedPopulation = 1_122_339_654;  



The C# 7 digit separator can be used with long, ulong, decimal, int, uint, short, ushort, double, byte, float data types.

Note: This article was originally published by me on C# Corner website here.

Data Type Suffixes In C#

Note: For all my blogs on Visual Studio / C# / .NET, please see here.

The objectives of this article are:

  • What is a data type suffix?
  • Why is a data type suffix required?
  • How and when to use a data type suffix?

What is a data type suffix?

In C#, while specifying any value of a variable or literal, a literal is a source code representation of a value and you can append some specific character after the value/literal, which is called a data type suffix. e.g.

  1. var myVal2 = 4294967296L;
  2. var myMoney = 300.5m;
  3. var myRadius = 3.145f;

As shown in the above examples, the L, m and f suffixed after the literals are data type suffixes.

For the scope of this article, I will cover the two types of literals given below to which data type suffixes can be applied:

  • integer-literal
  • real-literal

Why is a data type suffix required?

The data type suffix helps the compiler to unambiguously identify the data type of any value/literal. It also helps C# programmer to explicitly state the data type of the value/literal.

In the cases when a variable is declared, using one of the “var”, “dynamic” or “object” keywords, use the data type suffix to explicitly state the data type of the value.

In case of integer literals, if you don’t specify any suffix, then the integer values are evaluated to a data type, as per the sequence given below.

  • int
  • uint
  • long
  • ulong

In case of real- value literals (those with decimal points or fractions e.g. 3.14), if you don’t specify any suffix, then a real- value literal is evaluated to a data type, as per the sequence given below.

  • double
  • float/decimal (based on suffix)

In short, without any data type suffix, an integer literal will be evaluated to int and real literal will be evaluated to double.

There are data type suffixes given below.

  • L or l for long
    • (l in small letters should be avoided as it confuses you with digit 1)
  • D or d for double
  • F or f for float
  • M or m for decimal
    • (D is already taken for double, so M is best representation for decimal)
  • U or u for unsigned integer
  • UL or ul for unsigned long

There are no data type suffixes for int, byte, sbyte, short, ushort. Previous versions of C# used to have “Y” and “S” suffixes for byte and short respectively, but they were dropped from C# specification after being found, which are not often used by the programmers.

As a C# programmer, you should be aware of these data type suffixes and make use of them in your programming, so that you won’t have any surprises when your code is executed.

How and when to use a data type suffix?

As stated earlier, you as a programmer do not want C# compiler to decide the data type, as per default specification, then use the data type suffixes.

In the examples given below, I will show the usage in C#. Create a Visual Studio project for C# console Application and in the Program class, create the two methods given below:

public static void TestMethod(int i)
            Console.WriteLine("You called integer version of TestMethod");  

public static void TestMethod(long l)  
            Console.WriteLine("You called long version of TestMethod");  

You must have seen the code given above to create two overloaded methods with the same name “TestMethod” but different int and long arguments. There is not much logic in the method except the message to be written on the console to identify which one was called. You can imagine that there is a specific code here to do different operations for int and long data types.

Now, in Main method, write the two lines of code:




You must have noticed two different integer literals passed as parameters to TestMethod. How does the compiler now decide which method to call?

Press F5 to execute the program. You will see the result given below.


The literal “5” without any suffix got evaluated to int, hence the TestMethod with int parameter was called. The literal “5L” got evaluated to long, hence the TestMethod with long parameter was called.

Now, comment out the above three lines in Main method and write the code given below, followed by clicking F5.

var myVal1 = 429496;  


var myVal2 = 429496L;  


You will see the same output as in previous case due to the same reason.

Now, add the new overload of TestMethod in Program class given below.

public static void TestMethod(uint i)
 Console.WriteLine("You called UNSIGNED integer version of TestMethod");  

In Main method, write the code given below and click F5.

var myVal3 = 429496u;  



You will now see the third overloaded method and the one, which you just added will be called.


We will see now the programming in case of real value literals.

Comment out the above 3 lines, which you just added for unsigned int. In the Program class, create the three new overloaded methods given below.

public static void TestMethod(double i)
 Console.WriteLine("You called double version of TestMethod"); 

public static void TestMethod(float i) 
 Console.WriteLine("You called float version of TestMethod"); 

public static void TestMethod(decimal i) 
 Console.WriteLine("You called decimal version of TestMethod"); 

In the Main method, write code given below. Subsequently click F5 for the execution.

var myVal4 = 9.99;  


var myVal5 = 9999999999999999999999999999m;  


var myVal6 = 3.145f;  



You will see the output given below on the console.


Note here that any real literal (those values with fraction point/decimal) will be evaluated to double by default. Hence, the first call executed the TestMethod with double parameter.

A similar example with dynamic keyword is covered in my attached code, so I am not writing it here.

Let’s see what the compiler says when we use lower case.

Write the line given below in Main method, followed by clicking F6 to build the project.

var longTest = 12345l; 

Go to “Error List” Window and click Warning header to see the warning,

There is no error but it warns us to use capital L to denote long literal because lower case l can be easily confused with the digit 1.

Note: This article was first published by me on C# Corner website here.