Showing posts with label string. Show all posts
Showing posts with label string. Show all posts

Saturday, 6 April 2013

10 C#/.NET Features You May Not Know About

I thought it would be useful to document some of the typically lesser known features of the C# programming language and the .NET framework as a series of posts. Some of these features I've found useful and others I probably just haven't found a suitable use case for yet.

1. Anonymous Code Scopes in Methods

It's possible to have anonymous inner scopes within your method definitions. (I'm yet to come across a non-contrived use case for this!)
void MethodWithAnonymousScope()
{
    var helloPart = "Hello";

    {
        var worldPart = "world";
        Console.WriteLine("{0} {1}", helloPart, worldPart);
    }

    // "worldPart" doesn't resolve in this scope
}

2. Increment/Decrement Operator Position Significance

The position of the increment (++) and decrement (--) operators is significant. In the example below, when the increment operator is used as a postfix, it returns the value of 'number' before it has been incremented. Conversely, the prefix increment operator returns the value after it has been incremented. The decrement operator works with the same logic but decrements the number.
void PlusPlusOperator()
{
    var number = 0;

    Console.WriteLine(number++); // Outputs zero
    Console.WriteLine(++number); // Outputs two
}

3. The Default Keyword

The default keyword is a neat way to get the default value for a specified type. It's especially useful when working in a generic context.
void DefaultKeyword()
{
    var intDefault = default(int); // default(int) == 0
    var boolDefault = default(bool); // default(bool) == false

    // default(string) == null (as for all reference types)
    var stringDefault = default(string); 
}

4. Null-Coalescing Operator

The null-coalescing operator (??) provides a succinct way of returning a default value if your reference or nullable-value type is null. In the following example, if myNullableInteger (left operand) is not null, then it's returned, else the default value for int is returned (right operand).
int NullCoalescingOperator()
{
    int? myNullableInteger = SomeMethodThatCouldReturnNull();
    return myNullableInteger ?? default(int);
}

5. Short-Circuit Evaluation with Boolean Operators

The logical AND (&&) and OR (||) operators are short-circuit evaluated (left to right). For example, if the left operand of a logical AND is false, the right operand is not evaluated (as the whole condition will always be false). Similarly, if the left operand of a logical OR is true, the right operand is not evaluated. This can be demonstrated by observing the output of:
void ShortCircuitEvaluation()
{
    bool result;
            
    result = LeftOperand(true) || RightOperand(false);
    result = LeftOperand(false) || RightOperand(true);
    result = LeftOperand(true) && RightOperand(false);
    result = LeftOperand(false) && RightOperand(true);
}

bool LeftOperand(bool value)
{
    Console.WriteLine("Left operand evaluated");
    return value;
}

bool RightOperand(bool value)
{
    Console.WriteLine("Right operand evaluated");
    return value;
}
It's useful to know this so that you can safely perform multiple tests in a single if statement. In the example below, if myObject is null, the right operand is not evaluated (which is good because it'd cause a NullReferenceException).
if (myObject != null && myObject.SomeProperty == SomeValue)
    ...
Also note that if you use a single '&' and single '|' you bypass short-circuit evaluation and force the entire condition to be evaluated.

6. Aliases for Generic Types

You can assign an alias to a namespace but you can also assign an alias to a specific generic type to save yourself from typing the awkward generic syntax over and over again (especially useful when working with key/value pair based generic types where the value may also be a key/value pair!).
using StringList = System.Collections.Generic.List<string>;
...
void GenericAliases()
{
    // Can use the alias "StringList"
    // instead of List<string> 

    var stringList = new StringList();
    stringList.Add("Hello");
    stringList.Add("World");
    stringList.ForEach(Console.WriteLine);
}

7. Extension Methods on Dynamic Types

I came across this one when working with the dynamic ViewBag in ASP.NET MVC. As the title states, you cannot invoke an extension method on a type (that has the extension method defined for it and is in scope) which is dynamically typed. I have documented this one in this post (click to view). As the post shows, you have to call your extension method in the same fashion as you would call a standard static method, then pass your dynamically typed variable in as a parameter to the extension method.

8. System.String supports an Indexer

The string class has a readonly (get) char indexer defined on it, thus allowing you to access characters in the string using a zero-based index.
void StringIndexer()
{
    string message = "Hello, world!";

    for (int i = 0; i < message.Length; i++)
    {
        Console.WriteLine(message[i]); 
    }
}

9. Using foreach with System.String

The string class implements the IEnumerable<char> interface, which means that you can use the foreach statement on a string to enumerate through each character.
void ForeachWithString()
{
    string message = "Hello, world!";

    foreach (char character in message)
    {
        Console.WriteLine(character);
    }
}

10. Introspecting Code with Expression Trees

The System.Linq.Expressions.Expression class enables you to represent a code expression in a tree-based data structure that can then be used for introspection. This is a powerful feature which also then enables code modification in the expression tree (at runtime) and then subsequent compilation and execution.

The following example shows how we can wrap a simple lambda expression into an Expression, introspect the expression, compile the expression (in this case returning a Func<int, int, int>) and then execute the expression.
void Expressions()
{
    Expression<Func<int, int, int>> addExpression = (a, b) => a + b;

    foreach (var param in addExpression.Parameters)
    {
        Console.WriteLine(
            "Func Param Name: {0}, Param Type: {1}", 
            param.Name, 
            param.Type);
    }

    Console.WriteLine("Func return type: {0}", 
        addExpression.ReturnType);

    Console.WriteLine("10 + 20 = {0}", 
        addExpression.Compile()(10, 20));
                        
    // Can also use the Invoke method on the returned Func<...>
    // to aid readability
    // e.g. addExpression.Compile().Invoke(10, 20);
}
You may have indirectly used expression trees if you're an ASP.NET MVC developer. The HTML helper classes make extensive use of them, for example, the Html.TextBoxFor method has an overload that accepts a single parameter of type Expression<Func<dynamic, dynamic>>. An example call to this method would be @Html.TextBoxFor(m => m.FirstName) where 'm' is an instance of your view model. The TextBoxFor method uses the supplied expression (a lambda) to construct the HTML that is put back into the view. In this case it outputs an input element with an id and name attribute value of "FirstName" - which was retrieved using introspection (made possible with expression trees).

Sunday, 15 July 2012

Implementing Convert.ToInt32(string)

Earlier today I used the static helper method System.Convert.ToInt32(string). I thought it would be interesting to have a go at writing my own version of this method.
public static int ConvertToInt32(string integerAsString)
{
    var result = 0;
    var positiveSigned = integerAsString[0] == '+';
    var negativeSigned = integerAsString[0] == '-';

    for (var i = (positiveSigned || negativeSigned) ? 1 : 0; 
        i < integerAsString.Length; 
        i++)
    {
        var currentCharAsInt = (int) integerAsString[i] - (int) '0';

        if (currentCharAsInt < 0 || currentCharAsInt > 9)
            throw new ArgumentException(
                string.Format("The String value '{0}' " + 
                    "is not in a recognisable format.", 
                        integerAsString));

        result *= 10;
        result += currentCharAsInt;
    }

    return (negativeSigned) ? -result : result;
}

Thursday, 19 January 2012

String.ParseCsvToList Extension Method

A useful extension method to System.String. Given a comma-seperated list in a string, it'll return a generic List of type string, with each value occupying its own index.

public static List<string> ParseCsvToList(this string source)
{
    var valuesArray = source.Split(new char[] {','});
    return valuesArray.Select(value => value.Trim()).ToList();
}

Sunday, 18 December 2011

String.IsNullOrEmptyWhiteSpace Extension Method

This is hopefully the first of a series of related posts on some useful Extension methods that I've written. If you're not familiar with Extension methods then think of them as additional methods that you can add to any class you want additional functionality or behaviour for. For example, you can add a new method to the .NET BCL String class (as in this post). Prior to this feature, you could achieve this by deriving from a class and adding a new method in the deriving class, but Extension methods now give you a more reusable alternative. I'd recommend reading up on this topic by clicking here.

One thing I often find myself having to do is validate a string for not being empty. One fairly primitive way to accomplish this is to test for the following condition in an if statement:

input.Equals(string.Empty)
This will return true if input is an empty string. Sometimes, however, you need to also test if the input contains empty white space. Imagine if the user accidently hit the space key and the value for input was the string "  ". The test above would return false in such a case. To cater for such scenarios, I wrote the following extension method in a class library project.

public static bool IsNullOrEmptyWhiteSpace(this string str)
{
     return (str == null || str.Trim().Equals(string.Empty));
}
The test would now look like:

if (input.IsNullOrEmptyWhiteSpace())
     //Tell user to enter something
** Update (13/03/2013) **

As of .NET 4 the static method IsNullOrWhiteSpace was added to the String datatype, therefore making the extension method above redundant (unless you're still using earlier versions of the framework :).