Click here to Skip to main content
13,863,292 members
Click here to Skip to main content
Add your own
alternative version

Stats

72.8K views
430 downloads
88 bookmarked
Posted 16 Nov 2016
Licenced CPOL

C# Version 7 - Introduction to new language features

, 2 Jan 2017
Rate this:
Please Sign up or sign in to vote.
Let's get our hands dirty with new features of upcoming version 7 of C# language in .Net framework

Introduction

Let us dive into something really latest in the world of .Net. Microsoft is about to release a new version of C# language - version 7.0. Let's learn all its new features so that it can be handy whenever we upgrade our existing projects/solution to Visual Studio 15. 

Background

I was going through a wiki on C# language created by Jon Skeet (my most favourite developer on this planet) on stackoverflow.com website. Here is the link to the question which talks about version history of C# language.

C# language version wiki on stackoverflow.com

I suddenly noticed that the accepted answer doesn't mention the C# language version 7 which gave me a realization that it is not yet updated as the language version is yet to come to RTM milestone. So, I thought this particular language version is still in nascent phases of development so it will be exciting to share the detail of all new upcoming features in this language version to avid blog readers. Hence I incepted this article.

Prerequisites

A basic knowledge of C# language and Visual Studio (VS) IDE from Microsoft is desired while reading this article and for using the attached source code. 

A note for attached code

You need following softwares as prerequisite to run the attached code on your computer:

  1. Visual Studio 15 Preview 5 - First and foremost thing to understand is that Visual Studio 15 is NOT Visual Studio 2015. Visual Studio 2015 is the last RTMed version of Visual Studio which is currently available in market. Visual Studio 15 is the next Visual Studio version to be released in market. It will either be named (colloquial name) as Visual Studio 2016 or Visual Studio 2017 when it gets finally RTMed. 
  2. An active internet connection - This is needed to download the nuget packages referenced in the attached source code. Before creating a zip of the source code I emptied the packages directory because of its size (> 200 MB). The moment you rebuild the solution all the packages will get downloaded automatically if you have an active internet connection and then the sample code should run smoothly.

C# v7 features can work in VS 2015 also but that requires few configurations. So, best way to deal with this is to get the preview build of VS 15 from here. At the time of this writing the latest build is being named "Preview 5". Install VS 15 Preview 5 to get started. 

Note: C# v7 is not yet in RTM state. So, this feature list might not be exhaustive and complete from the final release stand-point. As the C# compiler team continues to work really hard, we can see more and more features working in new preview releases. Keep a watch on this blog post as I will keep updating it as more and more features become visible and runnable on Visual Studio 15. For absolutely latest updates you can check their GitHub page here.

Exploring the code for new features

Let's begin -

Feature # 1 - Binary literals

Old Behaviour:

Did not exist until C# v6.0

New Behaviour:

We have all used literal constant values for various primitive types in C# language. Here is the code snippet from attached source code which shows few literal constant declarations for some of the primitive types:

private static void ExistingPrimitiveTypeLiterals()
{
    int employeeNumber = 34; //integer literal constant
    float passPercentage = 34.0f; //float literal consntat
    int employeeAge = 0x22; //hexadecimal literal which is equivalent of decimal number 34
}

Until C# v6.0 there was no way for us to represent a binary literal value in code. C# v7.0 solves this problem in the upcoming version. They have introduced a new prefix "0b" (or "0B") whenever you want to declare a binary literal in your code. The underlying data type of such a variable will still be integer (System.Int32 or System.Int64) just like the way it was for hexdecimal numbers. These will be base 2 numerical numbers with 0 and 1 being only possible digits in such a representation. This is how you would be representing a binary literal in code:

private static void BinaryLiteralsFeature()
{
    var employeeNumber = 0b00100010; //binary equivalent of whole number 34. Underlying data type defaults to System.Int32
    Console.WriteLine(employeeNumber); //prints 34 on console.
    long empNumberWithLongBackingType = 0b00100010; //here backing data type is long (System.Int64)
    Console.WriteLine(empNumberWithLongBackingType); //prints 34 on console.
    int employeeNumber_WithCapitalPrefix = 0B00100010; //0b and 0B prefixes are equivalent.
    Console.WriteLine(employeeNumber_WithCapitalPrefix); //prints 34 on console.
}

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Feature # 2 - Digit Separators

Old Behaviour:

Did not exist until C# v6.0

New Behaviour:

Now you can improve readability of your long numeric literals by using underscore as digit separator. Use them anywhere and any number of times within the numeric literal as per your convenience. They will be especially useful in binary literals as they usually have long representations. Compiler simply ignores the underscores while compiling the code. Here is the code snippet from attached source code which shows digit separators in action:

private static void DigitSeparatorsFeature()
{
    //underscores coming in between the numbers have no impact on the underlying value being stored
    //it is simply to improve readability for long literal numerical values.
    int largeNaturalNumber = 345_2_45;
    int largeNaturalNumber_oldFormat = 345245;//same as above
    long largeWholeNumber = 1_2_3_4___5_6_7_8_0_10;
    long largeWholeNumber_oldFormat = 12345678010; //same as above
    int employeeNumber = 0b0010_0010; //specially useful in binary equivalents
}        

There are few restrictions though while using digit separators:

  • Underscore can't appear at the start of the number.
  • Underscore can't appear before decimal point.
  • Underscore can't appear after exponential sign.
  • Underscore can't appear before type specifier suffix.

Below piece of code showcases these beahviors.

private static void DigitSeparatorsFeature()
{
    int underscoreAtStarting = _23_34;//illegal! Will not compile
    int underscoreBeforeDecimalPoint = 10_.0;//illegal! Will not compile
    double underscoreAfterExponentialSign = 1.1e_1;//illegal! Will not compile
    float underscoreBeforeTypeSpecifier = 34.0_f//illegal! Will not compile
}

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Feature # 3 - Tuple data type now available as Value type

Old Behaviour:

Tuple data type was introduced as a new data type in C# v4.0. Until C# v6.0 it was available only as a reference data type inside System namespace. This is how you declare a generic Tuple variable in C# v6.0:

private static void TupleReferenceTypeLiterals()
{
    Tuple<int, string, bool> tuple = new Tuple<int, string, bool>(1, "cat", true);
    /*Console prints
     1
     cat
     true
     */
    Console.WriteLine(tuple.Item1); //compile creates public properties using a "Item" series based naming convention
    Console.WriteLine(tuple.Item2); //Item1, Item2 and Item3 properties start appearing in intellisense magically
    Console.WriteLine(tuple.Item3); 
}

Returning multiple values from a function was the primary usage of Tuples till date.

New Behaviour:

Using Tuples will become a cakewalk from upcoming version. Tuples will now be available as a value type. Tuples rely on the underlying type System.ValueTuple which is a struct. This type isn’t included in Preview 4 build. So, if you are using Preview 4 or an older build then you will have to add the underlying type via NuGet into your project using below mentioned steps:

  • Right-click the project in the solution explorer and select “Manage NuGet Packages…”
  • Select the “Browse” tab, check “Include prerelease” and select “nuget.org” as the “Package source”
  • Search for “System.ValueTuple” and install it.

  Here is how you define tuple literals in C# v7.0:

private static void TupleValueTypeLiterals()
{
    //types of struct members are automatically inferred by the compiler as string,string
    var genders = ("Male", "Female");
    Console.WriteLine("Possible genders in human race are : {0} and {1} ", genders.Item1, genders.Item2);
    Console.WriteLine($"Possible genders in human race are {genders.Item1}, {genders.Item2}.");

    //to override the default named Tuple public properties Item1 and Item2
    var geoLocation = new(double latitude, double longitude) { latitude = 124, longitude = 23 };
    Console.WriteLine("Geographical location is : {0} , {1} ", geoLocation.longitude, geoLocation.latitude);

    //hetrogeneous data types are also possible in tuple.
    var employeeDetail = ("Michael", 33, true); //(string,int,bool)
    Console.WriteLine("Details of employee are Name: {0}, Age : {1}, IsPermanent: {2} ", employeeDetail.Item1, employeeDetail.Item2, employeeDetail.Item3);

    //a reference type object can also be present as tuple member
    var employeeRecord = new(Employee emp, int Id) { emp = new Employee { FirstName = "Foo", LastName = "Bar" }, Id = 1 };
    Console.WriteLine("Employee details are - Id: {0}, First Name: {1}, Last Name: {2}", employeeRecord.Id, employeeRecord.emp.FirstName, employeeRecord.emp.LastName);
}

Tuples will also be a real boon for returning multiple values from a function. There had already been numerous ways in the language to return multiple values from a function but none of them had been as transparent and crisp as this newly introduced Tuples. So far you could have been using following ways to return multiple values from a function:

  • returning an array list
  • Define a struct and return it
  • Define a class with a public property each for the values to be returned
  • out parameters
  • returning a Tuple<T1,T2...Tn> type

What would be simpler than the one below.  Have a look!

static void Main(string[] args)
{
     //some code has been removed for brevity. Please download attached code for complete reference
     var geographicalCoordinates = ReturnMultipleValuesFromAFunction("London");
     Console.WriteLine(geographicalCoordinates.longitude);
     Console.WriteLine(geographicalCoordinates.Item1); //prints same as longitude
     Console.WriteLine(geographicalCoordinates.latitude);
     Console.WriteLine(geographicalCoordinates.Item2); //print same as latitude
}

private static (double longitude,double latitude) ReturnMultipleValuesFromAFunction(string nameOfPlace)
{
    var geoLocation = (0D, 0D);
    switch (nameOfPlace)
    {
        case "London":
            geoLocation = (24.9277, 84.1910);
            break;
        default:
            break;
    }
    return geoLocation;
}

Few very straight forward visible advantages of new Tuple type are as below:

  1. You don't have to create explicit type. Types are created on the fly as anonymous by the compiler.
  2. Now you can name the public members. In System.Tuple<T> compiler used to give generic names e.g. Item1, Item2, Item3 etc. to public members of the tuple.
  3. Internally the type is a struct so gets allocated on stack memory area. So, no heavy heap object allocation.

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Feature # 4 - Out parameters now have a fluid usage

Old Behaviour:

If you have ever used out parameter to get a return value from a function then you would remember the ugly way of declaring a variable before passing it to the out parameter of the function. Have a look:

private static void OutParameterOldUsage()
{
   var number = "20";
   int parsedValue; //pre-declare the variable to be passed as out argument
   int.TryParse(number, out parsedValue);
}

New Behaviour:

Now that has become really sweet and simple. The variable to be passed as the out parameter of the function call can be declared in-line with the function call itself as shown in the code snippet below:

private static void OutParameterNewUsage()
{
    var number = "20";
    //pre-declaration for out parameter variable NOT required anymore
    //int parsedValue;

    //inline declaration for out parameter variable.
    if (int.TryParse(number, out int parsedValue))
        Console.WriteLine(parsedValue);
    else
        Console.WriteLine("The input number was not in correct format!");

    //even var keyword would do
    if (int.TryParse(number, out var parsedValue2))
        Console.WriteLine(parsedValue2);
    else
        Console.WriteLine("The input number was not in correct format!");
}

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Feature # 5 - Local functions

Old Behaviour:

Did not exist until C# v6.0

New Behaviour:

This by far had been in the news the most since the proposed feature list was getting prepared for the new version of C# language. We often write functions representing complex and long algorithmic implementation. We often break the function into several multiple functions for clear understanding and easy maintenance. When we do so most of the times such smaller functions will not be reusable by other parts of your program/class as they are not generic enough and they are a specific step of your algorithmic problem you are solving currently.

Such functions which have got single place usage can now be defined as local functions so that they don't clutter unnecessarily and cause confusion. They are nested inside the function where they are to be called.

private static void LocalFunctionsFeature()
{
    //this function is not visible to any other function in this classs
    string GetAgeGroup(int age)
    {
        if (age < 10)
            return "Child";
        else if (age < 50)
            return "Adult";
        else
            return "Old";
    }

    Console.WriteLine("My age group is {0}", GetAgeGroup(33));
}

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Feature # 6 - Ref returns and ref locals

Old Behaviour:

If you haven been even an year older in .Net world then you must have used the ref keyword. In C#, by default parameters are passed by value i.e. a copy of the value is passed instead of the value itself. On the similar lines, another mechanism to pass parameters to a function is "Pass by Reference". In this case the actual value is passed instead of its copy. So, if you modify the argument (which has been passed by reference) inside the method body the corresponding argument present in the caller function will also get impacted. Have a look at below code snippet to unerstand it:

static void Main(string[] args)
{
    //some code has been removed for brevity. Please download attached code for complete reference
    Console.WriteLine("******Passing arguments by reference*********");
    string empName = "Foo";
    UpdateEmployeeName(ref empName);
    Console.WriteLine(empName);//prints Bar
}

private static void  UpdateEmployeeName(ref string empName)
{
    //this change will impact the variable in caller function which has
    //been passed by refence.
    empName = "Bar";
}

So, until C# v6.0 it was possible to use ref keyword only with input parameters of a function.

New Behaviour:

Well you might want to look at this SO thread and can see how someone's curiosity has actually turned out to be a feature in C# after five long years. Now from this new version of C# we can use ref keyword even with return value of the function. I noticed one thing. This feature is not an exact complement of passing values by reference into a function. It is not the case that you can simply declare a local variable inside your function and return its reference back to the caller. That's just not possible. As you know, all the variables local to a function are allocated on stack.  Stack frames and its corresponding memory allocation are trashed right after the function call finishes. So, your local variables cannot outlive the execution life time of a function.


Let's try to see how it can really be put to use in code. Ultimately what you can achieve is passing back the reference of a parameter which was passed by reference:

static void Main(string[] args)
{
    //some code has been removed for brevity. Please download attached code for complete reference
    Console.WriteLine("******ref locals and ref returns*********");
    int x = 10, y = 20;
    //after completion of the function newEmpNumber is actually an alias to variable y
    ref var newEmpNumber = ref GetBiggerNumber(ref x, ref y);
    //Now I'm actually incrementing y by below statement through newEmpNumber which is referring to y only
    newEmpNumber += 20;
    Console.WriteLine(y); //in reality y got incremented to 20 + 20 = 40

}

private static ref int GetBiggerNumber(ref int num1, ref int num2)
{
    //how to declare a ref local variable. Not really needed for the logic of this function
    ref int localVariable = ref num1; 
    //you are not returning a value but a reference.
    if (num1 > num2)
        return ref num1;
    else
        return ref num2;
}

Here localVariable is a ref local variable. I have showed it here just for showing the declaration syntax of ref local variables. It was not really needed for the logic of my function.

Honestly speaking, I'm myself not sure currently about the use case where I will this feature to use. As far as I am reading at several places, I can see this feature is more to pacify the needs of developers trying to port their code from C/C++.

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Feature # 7 - New possibility for throw expressions

Old Behaviour:

We have all used throw expressions whenever we want to take catch an exception, take some intermediate action and then throw the exception again to keep the error bubbling back to the caller or original call site in the call stack. Let's see this quickly how it works currently:

private static void SimpleThrowImplementation()
{
    int zero = 0;
    try
    {
        var result = 1 / zero;
    }
    catch (Exception ex)
    {
        //log the arithmetic exception in log file or event viewer
        //....
        //....
        //now throw the exception for the caller function to catch it and do appropriate handling.
        throw new ArithmeticException("Divide by zero exception occured in SimpleThrowApplication method");
    }
}

 

Until C# v6.0 a throw statement is always a stand-alone statement. It was not possible to club it with any other statement or expression.

New Behaviour:

Now C# v7.0 you can also use the throw statement in the middle of an expression e.g. a conditional ternary operator as shown in the code below:

private static int ThrowUsageInAnExpression(int value = 40)
{
    return  value < 20 ? value : throw new ArgumentOutOfRangeException("Argument value must be less than 20");
}

Current State in Visual Studio 15 Preview 5 Build:

Not working

 

Feature # 8 - New possibility for lambda expression bodied methods

Old Behaviour:

C# v6.0 had introduced expression bodied methods where you can define the body of the method as a lambda expression as shown in the code snippet below:

public class Employee
{
    private string _firstName;
    private string _lastName;

    public string GetFirstName() => _firstName;

}

But this usage had a lot of limitations as the same construct was not allowed while defining properties, constructors, finalizers etc.

New Behaviour:

Beginning C# v7.0 it is planned to allow expression bodied definition for properties, constructors, finalizers etc. also as shown in the code snippet below:

public class Employee
{
    private string _firstName;
    private string _lastName;

    //Not working in Visual Studio 15 Preview 5 currently. 
    public string FirstName
    {
        get => _firstName;                                 // getters
        set => _firstName = value;                         // setters
    }

}

Current State in Visual Studio 15 Preview 5 Build:

Not working

 

Feature # 9 - Pattern matching for types

Old Behaviour:

Did not exist until C# v6.0. Please do not confuse this feature with regular expression pattern matching. You all must have used System.Text.RegularExpressions.Regex class for doing string based pattern matching in C# e.g. to validate an email id being sent as input from the user. This new feature of pattern matching has nothing to do with string based pattern matching. This is completely new paradigm which has to do with matching of classes and types in C#.

New Behaviour:

Now pattern matching has been introduced for types also. These have been categorized as three types:

  • Constant patterns e.g. null, int.MaxValue
  • Type patterns e.g. int i
  • Var patterns e.g. var v

These are new concepts so I believe it will be easier to understand them by examples. Let us see all the above pattern types in action through is operator in C#. Here is the code snippet:

static void Main(string[] args)
{
    //some code has been removed for brevity. Please download attached code for complete reference.
  
    Console.WriteLine("******Pattern matching with Types*********");
    //prints nothing on console because of constant pattern matching inside the function call
    PatternMatchingFeatureWithTypes(2147483647);

    //prints nothing on console because of constant pattern matching inside the function call
    PatternMatchingFeatureWithTypes(null);

    //prints nothing on console because of type pattern mismatch inside the function call
    PatternMatchingFeatureWithTypes(5D);

    //print five asterisks on console because of type pattern matching inside the function call
    //Also prints a message on console because of var pattern matching inside the function call
    PatternMatchingFeatureWithTypes(5);

}

public static void PatternMatchingFeatureWithTypes(object input)
{
    //constant pattern "int.MaxValue"
    if (input is int.MaxValue)
    {
        return;
    }

    // constant pattern "null"
    if (input is null)
        return;

    // type pattern "int i"
    if (!(input is int i))
        return;

    //since type pattern got satisfied above so variable i get the value present in input parameter.
    Console.WriteLine(new string('*', i));

    //var pattern gets always satisfied for any type
    if (input is var v)
    {
        Console.WriteLine("var pattern will always have a match.");
    }
}

Let us see constant pattern and type pattern in action through switch-case expression in C#. You will also see a new keyword when getting used. Here is the code snippet:

class Program
{
    static void Main(string[] args)
    {
        //some code has been removed for brevity. Please download attached code for complete reference.
        Console.WriteLine("******Type Pattern matching in switch-case*********");
        var circleShape = new Circle();
        circleShape.Radius = 5;
        PatternMatchingFeatureWithSwitchCase(circleShape);
        var squareShape = new Rectangle();
        squareShape.Length = 10;
        squareShape.Width = 10;
        PatternMatchingFeatureWithSwitchCase(circleShape);

    }

    public static void PatternMatchingFeatureWithSwitchCase(object input)
    {
        var shape = input as Shape;
        if (shape != null)
        {
            switch (shape)
            {
                //use of type pattern
                case Circle c:
                    //if case gets satisfied then c actually starts to act as a variable which
                    //will get assigned the value of input variable after appropriate casting.
                    Console.WriteLine($"circle with radius {c.Radius}");
                    break;
                case Rectangle s when (s.Length == s.Width): //when is a new keyword in C#
                    Console.WriteLine($"{s.Length} x {s.Width} square");
                    break;
                case Rectangle r:
                    Console.WriteLine($"{r.Length} x {r.Width} rectangle");
                    break;
                default:
                    Console.WriteLine("<unknown shape>");
                    break;
                case null: //use of constant null pattern
                    throw new ArgumentNullException(nameof(shape));
            }
        }

    }


}



class Shape
{

}

class Circle : Shape
{
    public int Radius
    {
        get;
        set;
    }
}

class Rectangle : Shape
{
    public int Length
    {
        get;
        set;
    }

    public int Width
    {
        get;
        set;
    }
}

Current State in Visual Studio 15 Preview 5 Build:

Working

 

Points of Interest

Please comment if I've missed any of the features in case it is actually planned for the upcoming release but I've not included in my blog. For your interest, you can explore more on one such feature which I'm still exploring and trying to understand

  • Generalized async return types

History

16-Nov-2016 : First draft

22-Nov-2016 : Fixed formatting and grammar at several places.

25-Nov-2016 : Changed article tags for Visual Studio.

09-Dec-2016 : Fixed the title of feature # 4.

13-Dec-2016: Fixed error in feature # 1 based on reader's feedback.

17-Dec-2016: Fixed error in code snippet of feature # 8 based on reader's feedback.

03-Jan-2016: Fixed typographical error in code snippet of feature # 4 based on reader's feedback.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rasik Bihari Tiwari
Software Developer 1E
India India
My professional details will hardly make a difference to you if you have come to know about me after reading my lengthy article but my intent will make a difference for sure. Why I write articles is for the sole motto which I got to know pretty late in my career and that is that there is ONLY and ONLY one way of enhancing knowledge and that way is sharing. Blogs, articles and white papers are nothing but a form of sharing. It also helps you creating a backup copy of the knowledge you have in your brain and nerves. This backup copy will surely outlive your life as this knowledge gets transferred to uncountable people through sharing. So start contributing now! Always remember my favorite quote - "Knowledge is the ONLY antidote to all fears. Start reading a new book today". Don't seek Nirvana. Seek knowledge. Nirvana and knowledge are synonymous.

You may also be interested in...

Pro

Comments and Discussions

 
QuestionMy vote of 5 Pin
Vinod Jangle29-Mar-17 12:11
memberVinod Jangle29-Mar-17 12:11 
QuestionGreat read Pin
Pedro Güida3-Jan-17 7:04
memberPedro Güida3-Jan-17 7:04 
AnswerRe: Great read Pin
Rasik Bihari Tiwari3-Jan-17 15:52
professionalRasik Bihari Tiwari3-Jan-17 15:52 
GeneralRe: Great read Pin
Pedro Güida3-Jan-17 17:23
memberPedro Güida3-Jan-17 17:23 
QuestionQuestion about new behavior Pin
Avi Farah1-Jan-17 13:44
memberAvi Farah1-Jan-17 13:44 
QuestionThanks. Nice article Pin
Sri161226-Dec-16 19:07
memberSri161226-Dec-16 19:07 
AnswerRe: Thanks. Nice article Pin
Rasik Bihari Tiwari2-Jan-17 14:33
professionalRasik Bihari Tiwari2-Jan-17 14:33 
Question:) Pin
ankush.asthana23-Dec-16 23:04
memberankush.asthana23-Dec-16 23:04 
GeneralMy vote of 5 Pin
Forhad Reza21-Dec-16 11:13
memberForhad Reza21-Dec-16 11:13 
PraiseVote of 5 Pin
Clivic TR19-Dec-16 15:23
memberClivic TR19-Dec-16 15:23 
GeneralWeird code Pin
Dennis_E16-Dec-16 5:14
professionalDennis_E16-Dec-16 5:14 
PraiseRe: Weird code Pin
Rasik Bihari Tiwari16-Dec-16 17:00
professionalRasik Bihari Tiwari16-Dec-16 17:00 
QuestionCool Ada features - good job, but more to do!... Pin
gdemont13-Dec-16 23:14
membergdemont13-Dec-16 23:14 
QuestionMS overtook 30 y/o languages! :) Pin
Thornik12-Dec-16 13:51
memberThornik12-Dec-16 13:51 
QuestionLocal functions Pin
MikeTheFid12-Dec-16 12:52
memberMikeTheFid12-Dec-16 12:52 
QuestionFeature # 5 - Local functions Pin
Fitim Skenderi12-Dec-16 6:00
professionalFitim Skenderi12-Dec-16 6:00 
AnswerRe: Feature # 5 - Local functions Pin
Rasik Bihari Tiwari12-Dec-16 14:39
professionalRasik Bihari Tiwari12-Dec-16 14:39 
BugBinary literals - small error Pin
Julius Adam12-Dec-16 3:23
memberJulius Adam12-Dec-16 3:23 
PraiseRe: Binary literals - small error Pin
Rasik Bihari Tiwari12-Dec-16 14:53
professionalRasik Bihari Tiwari12-Dec-16 14:53 
QuestionNice article :thumbsup::thumbsup::thumbsup: Pin
tankSanju11-Dec-16 23:00
membertankSanju11-Dec-16 23:00 
GeneralMy vote of 5 Pin
Iftikhar Akram9-Dec-16 4:05
memberIftikhar Akram9-Dec-16 4:05 
QuestionNice blog Pin
Javed Bux29-Nov-16 16:38
professionalJaved Bux29-Nov-16 16:38 
GeneralMy vote of 5 Pin
Shashangka Shekhar29-Nov-16 16:32
mvaShashangka Shekhar29-Nov-16 16:32 
PraiseThanks. Nice article Pin
DotNetDev201627-Nov-16 19:54
memberDotNetDev201627-Nov-16 19:54 
GeneralMy vote of 5 Pin
Shmuel Zang27-Nov-16 18:49
memberShmuel Zang27-Nov-16 18:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190214.1 | Last Updated 2 Jan 2017
Article Copyright 2016 by Rasik Bihari Tiwari
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid