F# と C# の記法比較

MSDN F# リファレンスを使い C# と記法を比較する

null 値

null 値 Null Values

元ネタ http://msdn.microsoft.com/ja-jp/library/dd233197.aspx

.NET のメソッドに null 値を渡すには、呼び出し元のコードで null キーワードを使用します。

F#

open System

// Pass a null value to a .NET method.
let ParseDateTime (str: string) =
    let (success, res) = DateTime.TryParse(str, null, System.Globalization.DateTimeStyles.AssumeUniversal)
    if success then
        Some(res)
    else
        None

TryParse メソッドは、パースを行って成功/失敗を bool 値を返すと同時に、成功した場合は out で値を返す。 C# の場合は、ParseDateTime メソッドで戻り値を DateTime? にして、失敗の場合は null を返すようにする

C#

public DateTime? ParseDateTime(string str)
{
    DateTime res ;
    if (DateTime.TryParse(str, null, System.Globalization.DateTimeStyles.AssumeUniversal, out res))
        return res;
    else
        return null;
}

.NET のメソッドから取得した null 値を解釈するには、可能であればパターン マッチを使用します。 入力ストリームの末尾を超えて読み取ろうとしたときに ReadLine から返される null 値を、パターン マッチを使用して解釈する方法を次のコード例に示します。

F#

// Open a file and create a stream reader.
let fileStream1 =
    try
        System.IO.File.OpenRead("TextFile1.txt")
    with 
        | :? System.IO.FileNotFoundException -> printfn "Error: TextFile1.txt not found."; exit(1)

let streamReader = new System.IO.StreamReader(fileStream1)

// ProcessNextLine returns false when there is no more input;
// it returns true when there is more input.
let ProcessNextLine nextLine =
    match nextLine with
    | null -> false
    | inputString ->
        match ParseDateTime inputString with
        | Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
        | None -> printfn "Failed to parse the input."
        true

// A null value returned from .NET method ReadLine when there is
// no more input.
while ProcessNextLine (streamReader.ReadLine()) do ()

F# の場合は一時的な関数をその場で書けるが、C# の場合はメソッド化しないといけない。

C#

public void test()
{
    System.IO.FileStream fileStream1 = null;
    try {
        fileStream1 = System.IO.File.OpenRead("TextFile1.txt");
    } catch ( System.IO.FileNotFoundException ex ) {
        Console.WriteLine("Error: TextFile1.txt not found.");
        return ;
    }
    var streamReader = new System.IO.StreamReader(fileStream1);
    // A null value returned from .NET method ReadLine when there is
    // no more input.
    while (ProcessNextLine(streamReader.ReadLine())) ;
}
bool ProcessNextLine(string nextLine)
{
    switch (nextLine)
    {
        case null: 
            return false;
        default:
            var date = ParseDateTime(nextLine);
            if (date != null)
            {
                Console.WriteLine("{0}", date.Value.ToLocalTime().ToString());
            }
            else
            {
                Console.WriteLine("Failed to parse the input.");
            }
            return true;
    }
}

ただし、必ずメソッド化しないと駄目というわけでもなく、ラムダ式を使うと似た感じで書ける。

C#

public void test2()
{
    System.IO.FileStream fileStream1 = null;
    try
    {
        fileStream1 = System.IO.File.OpenRead("TextFile1.txt");
    }
    catch (System.IO.FileNotFoundException ex)
    {
        Console.WriteLine("Error: TextFile1.txt not found.");
        return;
    }
    var streamReader = new System.IO.StreamReader(fileStream1);

    Func<string, bool> ProcessNextLine = nextLine =>
    {
        switch (nextLine)
        {
            case null:
                return false;
            default:
                var date = ParseDateTime(nextLine);
                if (date != null)
                {
                    Console.WriteLine("{0}", date.Value.ToLocalTime().ToString());
                }
                else
                {
                    Console.WriteLine("Failed to parse the input.");
                }
                return true;
        }
    };
    // A null value returned from .NET method ReadLine when there is
    // no more input.
    while (ProcessNextLine(streamReader.ReadLine())) ;
}

F# の型に対する null 値は、Unchecked.defaultof を呼び出す Array.zeroCreate を使用する場合など、別の方法でも生成されることがあります。

F#

match box value with
| null -> printf "The value is null."
| _ -> printf "The value is not null."

box を使う必要は C# ではないと思われる。