『スラスラわかるC#』第9章 読書メモ

スラスラわかるC# (Beginner’s Best Guide to Programmin)

ジェネリック

ジェネリックを使うことで、メソッドを任意の型に対応させることができる。

using System;

namespace Sample
{
    class Program
    {
        static T Max<T>(T a, T b) where T : IComparable
        {
            return a.CompareTo(b) > 0 ? a : b;
        }

        static void Main(string[] args)
        {
            Console.WriteLine(Max(1, 2));
            Console.WriteLine(Max(3.1, 2.2));
        }
    }
}

上記コードで、Tの部分には任意の型が入る。Max(1,2)ならint、Max(1.1, 2.1)ならdoubleで演算が行われる。whereで、Tの型にIComparebleを実装しているという制約を加えている。また、ジェネリックを使うと演算子を利用できなくなるため、比較にはIComparebleで実装が保証されているCompareメソッドを使用している。

ジェネリックなクラスは以下のように定義し、利用する。

using System;

namespace Sample
{
    class Stack<T>
    {
        T[] buf;
        int top;
        public Stack(int max) { this.buf = new T[max]; }
        public void Push(T val) { this.buf[this.top++] = val; }
        public T Pop() { return this.buf[--this.top]; }
        public int Size { get { return this.top; } }
        public int MaxSize { get { return this.buf.Length; } }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var iStack = new Stack<int>(4);
            var dStack = new Stack<double>(5);

            for (int i = 1; i <= iStack.MaxSize; ++i)
            {
                iStack.Push(i);
            }

            while (iStack.Size > 0)
            {
                Console.WriteLine("{0}", iStack.Pop());
            }
        }
    }
}

defaultキーワード

default(Type)はTypeが数値型の場合は0、参照型の場合はnullを返す。

using System;

namespace Sample
{
    class Program
    {
        static void FillWithDefault<T>(T[] array)
        {
            for (int i = 0, len = array.Length; i < len; ++i)
            {
                array[i] = default(T);
            }
        }

        static void Main(string[] args)
        {
            int[] array = new int[5];

            FillWithDefault(array);

            foreach (int n in array)
            {
                Console.WriteLine(n);
            }
        }
    }
}

共変性と反変性

C#4.0以上では、ジェネリックの型のパラメータに共変性・反変性を持たせることができる。

正直言って、この本だけだと共変性と反変性はよく理解できなかった。MSDNのジェネリックの共変性と反変性の方が、コード例が豊富でわかりやすい。

共変性は指定された型と、その派生元の型を使用できること。反変性は、指定された型と、その派生型を使用できること。指定された型のみが使用できる場合は不変性という。

using System;
using System.Collections.Generic;

namespace Sample
{
    class Base { }

    class Derived : Base { }

    class Program
    {
        static void Main(string[] args)
        {
            // IEnumerable<out T> と定義されているので、Derivedの派生元のBaseも使える
            IEnumerable<Derived> ed = new List<Derived>();
            IEnumerable<Base> eb = ed;

            // Action<in T> と定義されているので、Baseの派生型のDerivedも使える
            Action<Base> ab = (target) => { Console.WriteLine(target.GetType().Name); };
            Action<Derived> ad = ab;
            ad(new Derived());
        }
    }
}

正直言って、まだちゃんと理解できているとはいいがたい。もう少し実例を通して学んでいきたい。

コメントをどうぞ

コメントを残す