3

わかった。そのため、現在、インターフェイスをパラメーターとして受け取るC#でインターフェイスのリストを作成しようとしています。これをより明確にするために、例を挙げましょう。

public interface IPlate<T> where T : IWaffle {}
public interface IWaffles {}

public class BelgiumWaffle : IWaffle {}
public class FalafelWaffle : IWaffle {}
public class HugePlate : IPlate<BelgiumWaffle> {}
public class SmallPlate : IPlate<FalafelWaffle> {}


// Now, I want to do the following:
var plates = new List<IPlate<IWaffle>>();
plates.add(new HugePlate());
plates.add(new SmallPlate());

目標は、IPlate オブジェクトのリストを XML にシリアル化できるようにすることです。これを行うためにジェネリックを使用したいと思っていましたが、追加しようとするといくつかの引数エラーがあるというエラーが表示され続けます(別名-型が一致しません)。ここで何が間違っているのかわかりません。私には正しいように思えますが、何かが欠けているに違いありません(明らかに)。

更新:これは.NET v3.5であることを言及する必要があります

更新:申し訳ありません!Plate クラスの定義に関する質問を書く際のいくつかのタイプミス。

4

6 に答える 6

4

共分散を使用する必要があると思います (.NET 4.0)

public interface IPlate<out T> where T : IWaffle {}

IPancakeと置き換えますIWaffle

var plates = new List<IPlate<IPancake>>();
于 2012-10-25T13:56:46.630 に答える
2

リストが必要とするインターフェースを実装HugePlateSmallPlate実装もしていません。IPlate<IPancake>plates

于 2012-10-25T13:58:43.700 に答える
1

.NET Framework 3.5では、.NETFramework4.0のようにジェネリック共分散outで使用するパラメーターがありません。

非ジェネリックバージョンのIPlate(この場合は名前を付けますIPlateNG)を使用して、回避策を試すことができます。

.NET Framework 4.0の次の例を検討してください(要点を示すために拡張する必要がありました)。

using System;
using System.Collections.Generic;

public interface IWaffle { string Eat(); }
// on C# 4.0 you just put the "out" to mark the covariance (and that is it)
public interface IPlate<out T> where T : IWaffle { T GetMyWaffle(); }

public class BelgiumWaffle : IWaffle {
    public string Eat() { return "Eating a Belgium Waffle"; }
    public string Breakfast() { return "Breakfasting a Belgium Waffle"; }
}
public class FalafelWaffle : IWaffle {
    public string Eat() { return "Eating a Falafel Waffle"; }
    public string Dinner() { return "Having dinner with a Falafel Waffle"; }
}
public class HugePlate : IPlate<BelgiumWaffle> {
    public BelgiumWaffle GetMyWaffle() { return new BelgiumWaffle(); }
}
public class SmallPlate : IPlate<FalafelWaffle> {
    public FalafelWaffle GetMyWaffle() { return new FalafelWaffle(); }
}

class Program
{
    static void Main(string[] args)
    {
        var plates = new List<IPlate<IWaffle>>();
        plates.Add(new HugePlate());
        plates.Add(new SmallPlate());

        IPlate<IWaffle> aPlate = plates[0];
        // Anyway, when you get a member of the collection you'll get the interface, not a concrete class (obviously).
        IWaffle aWaffle = aPlate.GetMyWaffle();
        // So you cannot invoke any specifics (like Breakfast or Dinner)
        Console.WriteLine(aWaffle.Eat());

        // But if you cast the member of the collection to the specific class (or interface)
        IPlate<FalafelWaffle> aSmallPlate = (SmallPlate)plates[1];
        // Then you'll get the concrete class without casting again
        FalafelWaffle aFalafel = aSmallPlate.GetMyWaffle();
        Console.WriteLine(aFalafel.Dinner());
    }
}

これで、これは.NETFramework3.5でも同じになります。

using System;
using System.Collections.Generic;

public interface IWaffle { string Eat(); }
// In this case I define this extra inteface which is non-generic
// And inside it, we need a new method equivalent to the one on the generic one
public interface IPlateNG { IWaffle GetWaffle(); }
// And make the generic one implement the non-generic one
public interface IPlate<T> : IPlateNG where T : IWaffle { T GetMyWaffle(); }

public class BelgiumWaffle : IWaffle {
    public string Eat() { return "Eating a Belgium Waffle"; }
    public string Breakfast() { return "Breakfasting a Belgium Waffle"; }
}
public class FalafelWaffle : IWaffle {
    public string Eat() { return "Eating a Falafel Waffle"; }
    public string Dinner() { return "Having dinner with a Falafel Waffle"; }
}
public class HugePlate : IPlate<BelgiumWaffle> {
    // This extra method is needed due the lack of the 'out' on the definition
    public IWaffle GetWaffle() { return GetMyWaffle(); }
    public BelgiumWaffle GetMyWaffle() { return new BelgiumWaffle(); }
}
public class SmallPlate : IPlate<FalafelWaffle> {
    // This extra method is needed due the lack of the 'out' on the definition
    public IWaffle GetWaffle() { return GetMyWaffle(); }
    public FalafelWaffle GetMyWaffle() { return new FalafelWaffle(); }
}

class Program
{
    static void Main(string[] args)
    {
        // The list cannot work with the IPlate<IWaffle> anymore. So here comes IPlateNG to the rescue
        var plates = new List<IPlateNG>();
        plates.Add(new HugePlate());
        plates.Add(new SmallPlate());

        IPlateNG aPlate = plates[0];
        // And instead of calling to the GetMyWaffle method we can call to the GetWaffle in this case
        IWaffle aWaffle = aPlate.GetWaffle();
        Console.WriteLine(aWaffle.Eat());

        IPlate<FalafelWaffle> aSmallPlate = (SmallPlate)plates[1];
        FalafelWaffle aFalafel = aSmallPlate.GetMyWaffle();
        Console.WriteLine(aFalafel.Dinner());
    }
}

この「 out」キーワードの欠如を回避するために、両方の具象クラスでGetMyWaffle(named )の追加の非ジェネリックバージョンを作成する必要があることに注意してください。しかし、残りはかなり似ています。GetWaffleIPlate

于 2012-10-25T16:23:21.077 に答える
1

共分散 (@JakubKonecki によって既に指摘されているように) に加えて、HugePlate と SmallPlate の定義は、実装する必要があるため、正しくないように見えますIPlate

これを試して:

public interface IPlate<out T> where T : IWaffle {}
public interface IWaffle {}

public class BelgiumWaffle : IWaffle {}
public class FalafelWaffle : IWaffle {}
public class HugePlate<T> : IPlate<T> where T : IWaffle {}
public class SmallPlate<T> : IPlate<T> where T : IWaffle {}
于 2012-10-25T14:11:52.647 に答える
0

共分散について指摘した@JakubKoneckiのおかげで、3.5で動作します

    public interface IWaffle { }
    public interface IPlate<out T> where T : IWaffle { }
    public interface IPancake : IWaffle { }

    public class BelgiumWaffle : IWaffle {}
    public class FalafelWaffle : IWaffle {}
    public class HugePlate : IPlate<BelgiumWaffle> {}
    public class SmallPlate : IPlate<FalafelWaffle> { }

    var plates = new List<IPlate<IWaffle>>();
    plates.Add(new HugePlate());
    plates.Add(new SmallPlate());
于 2012-10-25T14:12:39.670 に答える
0

T のインターフェイスの代わりに抽象クラスを使用できますか?

public abstract class Waffle { }
public interface IPlate<T> where T : Waffle
{
    T Food
    {
        get;
        set;
    }
}

public class BelgiumWaffle : Waffle { }
public class FalafelWaffle : Waffle { }
public class HugePlate<T> : IPlate<T> where T : Waffle
{
    public HugePlate(T food)
    {
        this.Food = food;
    }

    public T Food
    {
        get;
        set;
    }
}

public class SmallPlate<T> : IPlate<T> where T : Waffle
{
    public SmallPlate(T food)
    {
        this.Food = food;
    }

    public T Food
    {
        get;
        set;
    }
}

public class Test
{
    Test()
    {
        var platesOfWaffle = new List<IPlate<Waffle>>();
        platesOfWaffle.Add(new HugePlate<Waffle>(new BelgiumWaffle()));
        platesOfWaffle.Add(new SmallPlate<Waffle>(new FalafelWaffle()));
    }
}
于 2012-10-25T15:17:48.810 に答える