English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# 単方向変換と逆変換

変換と逆変換は、クラス階層を処理する際により柔軟にさせています。

変換と逆変換を学ぶ前に、以下のクラス階層を見てください:

public class Small
{ 
}
public class Big: Small
{
}
public class Bigger : Big
{ 
    
}

上記の例クラスに基づいて、Small は Big の基底クラスであり、Big は Bigger の基底クラスです。ここで覚えておくべきポイントは、派生クラスは常に基底クラスよりも多くのものを持つため、基底クラスは派生クラスよりも小さいということがあります。

今、以下の初期化を見てみましょう:

クラスの初期化

上記のように、基底クラスは派生クラスを収容できますが、派生クラスは基底クラスを収容できません。言い換えれば、インスタンスは小さい場合でも大きなものを受け入れできますが、大きい場合には小さいものを受け入れられません。

今、変換と逆変換について学びましょう。

C# 単方向変換(Covariance)

変換は、派生型を持つことができることを許可し、その際には基型が必要です。変換は同型の方差のようなものです。基底クラスと他の派生クラスは、基底型に追加機能を提供する同じクラスと考えられます。したがって、変換は基底クラスが必要な場所で派生クラスを使用することができます(小クラスが必要な場合、ルール:大きいクラスを受け入れできます)。

協変はデリゲート、ジェネリクス、配列、インターフェースなどに適用できます。

デリゲート協変

デリゲート内の協変は、デリゲートメソッドの返却タイプに柔軟性を提供します。

public delegate Small covarDel(Big mc);
public class Program
{
    public static Big Method1(Big bg)
    {
        Console.WriteLine("Method1");
    
        return new Big();
    }
    public static Small Method2(Big bg)
    {
        Console.WriteLine("Method2");
    
        return new Small();
    }
        
    public static void Main(string[] args)
    {
        covarDel del = Method1;
        Small sm1 = del(new Big());
        del= Method2;
        Small sm2 = del(new Big());
    }
}
出力:
メソッド1
メソッド2

ご覧の通り、デリゲートはSmall(基底クラス)の返却タイプを期待していますが、Big(派生クラス)の返却するMethod1およびデリゲートが期待するシグネチャと同じMethod2。

したがって、協変は、より多くの派生返却タイプを持つデリゲートにメソッドを割り当てることを許可します。

C# 逆変 (Contravariane)

コントラバリアンス(逆変)をパラメータに適用。 コントラバリアンス(逆変)は、派生クラスのパラメータを基クラスのパラメータに割り当てるメソッドのデリゲートに許可します。

上記の例に続いて、デリゲートとは異なる引数タイプを持つMethod3:

delegate Small covarDel(Big mc);
class Program
{
    static Big Method1(Big bg)
    {
        Console.WriteLine("Method1");
        return new Big();
    }
    static Small Method2(Big bg)
    {
        Console.WriteLine("Method2");
        return new Small();
    }
    static Small Method3(Small sml)
    {
        Console.WriteLine("Method3");
        
        return new Small();
    }
    static void Main(string[] args)
    {
        covarDel del = Method1;
        del += Method2;
        del += Method3;
        Small sm = del(new Big());
}
出力:
メソッド1
メソッド2
メソッド3

ご覧の通り、Method3Smallクラスの引数を持っており、デリゲートはBigクラスの引数を期待しています。 ただし、Method3デリゲートと一緒に使用。

以下のように同じ方法で協変と逆変を使用できます。

例:協変と逆変の使用
delegate Small covarDel(Big mc);class Program
{    static Big Method}}4(Small sml)
    {        Console.WriteLine("Method3");    
        return new Big();
    }
    {        covarDel del = Method4;    
        Small sm = del(new Big());
    }
}
出力:
メソッド4