Dotnetfreaks' Blog | LINQ

Dotnetfreaks' Blog

Fabulous Adventures In DotNet

About the author

Author Name is someone.
E-mail me Send mail

Recent posts

Recent comments

Archive

Tags

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012

Nullable Types (System.Nullable)


As you know, a variable of a value type can never be null; it always contains the value type's value itself. In fact, this is why they call value types value types. Unfortunately, there are some scenarios in which this is a problem.

Examples:

Case 1: When designing a database, it's possible to define a column's data type to be a 32-bit integer that would map to the FCL's Int32 data type. But a column in a database can indicate that the value is nullable. That is, it is OK to have no value in the row's column. Working with database data by using the Microsoft .NET Framework can be quite difficult because in the common language runtime (CLR), thereis no way to represent an Int32 value as null.

Case 2:  In Java, the java.util.Date class is a reference type, and therefore, a variable of this type can be set to null. However, in the CLR, a System.DateTime is a value type, and a DateTime variable can never be null. If an application written in Java wants  to communicate a date/time to a Web service running the CLR, there is a problem if the Java application sends null because the CLR has no way to represent this and operate on it.

To improve this situation, Microsoft added the concept of nullable value types to the CLR. To understand how they work, we first need to look at the System.Nullable<T> class, which is defined in the FCL. Here is the logical representation of how the System.Nullable<T> type is defined:

 using System;
namespace System
{
    using System.Globalization;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Security;

    // Warning, don't put System.Runtime.Serialization.On*Serializ*Attribute
    // on this class without first fixing ObjectClone::InvokeVtsCallbacks
    // Also, because we have special type system support that says a a boxed Nullable<T>
    // can be used where a boxed<T> is use, Nullable<T> can not implement any intefaces
    // at all (since T may not). Do NOT add any interfaces to Nullable!
    //
    [TypeDependencyAttribute("System.Collections.Generic.NullableComparer`1")]
    [TypeDependencyAttribute("System.Collections.Generic.NullableEqualityComparer`1")]
    [Serializable()]
    public struct Nullable<T> where T : struct
    {
        private bool hasValue;
        internal T value;

        public Nullable(T value)
        {
            this.value = value;
            this.hasValue = true;
        }

        public bool HasValue
        {
            get { return hasValue; }
        }

        public T Value
        {
            get
            {
                if (!HasValue)
                {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
                }
                return value;
            }
        }

        public T GetValueOrDefault()
        {
            return value;
        }

        public T GetValueOrDefault(T defaultValue)
        {
            return HasValue ? value : defaultValue;
        }

        public override bool Equals(object other)
        {
            if (!HasValue)
                return other == null;
            if (other == null)
                return false;
            return value.Equals(other);
        }

        public override int GetHashCode()
        {
            return HasValue ? value.GetHashCode() : 0;
        }

        public override string ToString()
        {
            return HasValue ? value.ToString() : "";
        }

        public static implicit operator Nullable<T>(T value)
        {
            return new Nullable<T>(value);
        }

        public static explicit operator T(Nullable<T> value)
        {
            return value.Value;
        }

        // The following already obsoleted methods were removed:
        // public int CompareTo(object other)
        // public int CompareTo(Nullable<T> other)
        // public bool Equals(Nullable<T> other)
        // public static Nullable<T> FromObject(object value)
        // public object ToObject()
        // public string ToString(string format)
        // public string ToString(IFormatProvider provider)
        // public string ToString(string format, IFormatProvider provider)

        // The following newly obsoleted methods were removed:
        // string IFormattable.ToString(string format, IFormatProvider provider)
        // int IComparable.CompareTo(object other)
        // int IComparable<Nullable<T>>.CompareTo(Nullable<T> other)
        // bool IEquatable<Nullable<T>>.Equals(Nullable<T> other)
    }
}

As you can see, this class encapsulates the notion of a value type than can also be null. Since Nullable<T>  is itself a value type, instances of it are still fairly lightweight. That is, instances can still be on the stack, and an instance is the same size as the original value type plus the size of a Boolean field. Notice that Nullable's type parameter, T, is constrained to struct. This was done because reference type variables can already be null.

So now, if you want to use a nullable Int32 in your code, you can write something like this:

Nullable<Int32> x = 5;
Nullable<Int32> y = null;
Console.WriteLine("x: HasValue={0}, Value={1}",
x.HasValue, x.Value);
Console.WriteLine("y: HasValue={0} , Value={1}",
y.HasValue, y.GetValueOrDefault());


When I compile and run this code, I get the following output:

x: HasValue=True, Value=5
y: HasValue=False, Value=0

 

C#'s Null-Coalescing Operator

C# has an operator called the null-coalescing operator (??), which takes two operands. If the operand on the left is not null,  the operand's value is returned. If the operand on the left is null,  the value of the right operand is returned. The null-coalescing operator offers a very convenient way to set a variable's default value.

A cool feature of the null-coalescing operator is that it can be used with reference types as well as nullable value types. Here is some code that demonstrates the use of the null-coalescing operator:

private static void NullCoalescingOperator() {
    Int32? b = null;
    // The line below is equivalent to:
    // x = (b.HasValue) ? b.Value : 123
    Int32 x = b ?? 123;
    Console.WriteLine(x); // "123"
}

 




Posted by Ajander Singh on Saturday, March 07, 2009 8:29 PM
Permalink | Comments (0) | Post RSSRSS comment feed

The CLR Has Special Support for Nullable Value Types


The CLR has built-in support for nullable value types. This special support is provided for boxing, unboxing, calling GetType, and calling interface methods, and it is given to nullable types to make them fit more seamlessly into the CLR. This also makes them behave more naturally and as most developers would expect. Let's take a closer look at the CLR's special support for nullable types.




Posted by Ajander Singh on Wednesday, January 07, 2009 10:28 PM
Permalink | Comments (0) | Post RSSRSS comment feed

LINQ(Language Integrated Query)


Using LINQ, we are able to create directly within the C# programming language entities called query expressions. These query expressions are based on numerous query operators that have been intentionally designed to look and feel very similar (but not quite identical) to a SQL expression. 

Core LINQ assemblies:

 System.Core.dll

Defines the types that represent the core LINQ API. This is the one assembly you must have access to. 

System.Data.Linq.dll 

Provides functionality for using LINQ with relational databases (LINQ to SQL). 

System.Xml.Linq.dll 

Defines a handful of types to integrate ADO.NET types into the LINQ programming paradigm (LINQ to DataSet). 

System.Data.DataSetExtensions.dll 

Provides functionality for using LINQ with XML document data (LINQ to XML). 


First, A Taste of LINQ

    static void QueryOverStrings()
    {
        // Assume we have an array of strings.
        string[] currentVideoGames = {"Morrowind", "BioShock",
        "Half Life 2: Episode 1", "The Darkness",
        "Daxter", "System Shock 2"};
        // Build a query expression to represent the items in the array that have more than 6 letters.
        IEnumerable<string> subset = from g in currentVideoGames
        where g.Length > 6 orderby g select g;
        // Print out the results.
        foreach (string s in subset)
        Console.WriteLine("Item: {0}", s);
    }

 Query Expressions

        from itemName in srcExpr
        join itemName in srcExpr on keyExpr equals keyExpr
        (into itemName)?
        let itemName = selExpr
        where predExpr
        orderby (keyExpr (ascending | descending)?)*
        select selExpr
        group selExpr by keyExpr
        into itemName query-body





Posted by Ajander Singh on Monday, June 09, 2008 4:08 PM
Permalink | Comments (0) | Post RSSRSS comment feed