列表<;T<;U>&燃气轮机;在c#中,T和U是接口

列表<;T<;U>&燃气轮机;在c#中,T和U是接口,c#,.net,generics,.net-3.5,C#,.net,Generics,.net 3.5,好的。因此,我目前正在尝试在C#中创建一个接口列表,该列表将接口作为参数。为了更清楚地说明这一点,让我举一个例子: public interface IPlate<T> where T : IWaffle {} public interface IWaffles {} public class BelgiumWaffle : IWaffle {} public class FalafelWaffle : IWaffle {} public class HugePlate : IPl

好的。因此,我目前正在尝试在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,其中T:IWaffle{}
公共接口IWaffles{}
公共类BelgiumWaffle:IWaffle{}
公共类法拉费华夫饼干:IWaffle{}
公共类HugePlate:IPlate{}
公共类SmallPlate:IPlate{}
//现在,我想做以下工作:
var板=新列表();
添加(新的HugePlate());
添加(新的小板());
目标是能够将IPlate对象列表序列化为XML。我希望使用泛型来实现这一点,但我不断收到错误,告诉我在尝试添加时存在一些参数错误(aka-类型不匹配)。只是不知道我做错了什么。对我来说这似乎是对的,但我肯定错过了什么(显然)

更新:我应该提到这是.NET v3.5


更新:对不起!在写关于板块类别定义的问题时有一些拼写错误。

我认为你应该使用协方差(.NET 4.0)


既不是
HugePlate
也不是
SmallPlate
实现
IPlate
接口,该接口是
plates
列表所需的

除了协方差(正如@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 {}
公共接口IPlate,其中T:IWaffle{}
公共接口IWaffle{}
公共类BelgiumWaffle:IWaffle{}
公共类法拉费华夫饼干:IWaffle{}
公共类HugePlate:IPlate其中T:IWaffle{}
公共类SmallPlate:IPlate其中T:IWaffle{}

在3.5中起作用,这要感谢@JakubKonecki指出了协方差

    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());
公共接口IWaffle{}
公共接口IPlate,其中T:IWaffle{}
公共接口IPancake:IWaffle{}
公共类BelgiumWaffle:IWaffle{}
公共类法拉费华夫饼干:IWaffle{}
公共类HugePlate:IPlate{}
公共类SmallPlate:IPlate{}
var板=新列表();
添加(新的HugePlate());
添加(新的小板());

是否可以使用抽象类而不是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()));
    }
}
公共抽象类华夫格{}
公共接口IPlate,其中T:Waffle
{
T食品
{
得到;
设置
}
}
公共类BelgiumWaffle:Waffle{}
公共类FalafelWaffle:Waffle{}
公共类HugePlate:IPlate其中T:Waffle
{
公共雨果板(T食品)
{
这个。食物=食物;
}
公共卫生食品
{
得到;
设置
}
}
公共类小板:IPlate,其中T:华夫饼
{
公共小盘(T食品)
{
这个。食物=食物;
}
公共卫生食品
{
得到;
设置
}
}
公开课考试
{
测试()
{
var platesOfWaffle=新列表();
platesOfWaffle.Add(新的HugePlate(新的BelgiumWaffle());
添加(新的小板(新的FalafelWaffle());
}
}

在.NET Framework 3.5中,您没有要在泛型协方差上使用的
out
参数,就像在.NET Framework 4.0中一样

您可以尝试使用非通用版本的
IPlate
(在本例中,我将其命名为
IPlateNG

考虑.NET Framework 4.0中的以下示例(我必须展开它来说明我的观点):

使用系统;
使用System.Collections.Generic;
公共接口IWaffle{string Eat();}
//在C#4.0上,您只需输入“out”来标记协方差(就是这样)
公共接口IPlate,其中T:IWaffle{T GetMyWaffle();}
公共类BelgiumWaffle:IWaffle{
公共字符串Eat(){返回“吃比利时华夫饼”;}
公共字符串早餐(){return“早餐吃比利时华夫饼”;}
}
公共级法拉费华夫饼干:IWaffle{
公共字符串Eat(){return“吃法拉菲尔华夫饼”;}
公共字符串晚餐(){return“与法拉菲尔华夫饼共进晚餐”;}
}
公共类HugePlate:IPlate{
public BelgiumWaffle GetMyWaffle(){return new BelgiumWaffle();}
}
公共类小型板:IPlate{
公共FalafelWaffle GetMyWaffle(){返回新的FalafelWaffle();}
}
班级计划
{
静态void Main(字符串[]参数)
{
var板=新列表();
添加(新的HugePlate());
添加(新的小板());
IPlate aPlate=板[0];
//无论如何,当您获得集合的成员时,您将获得接口,而不是具体的类(显然)。
IWaffle aWaffle=aPlate.GetMyWaffle();
//所以你不能引用任何细节(比如早餐或晚餐)
Console.WriteLine(aWaffle.Eat());
//但是如果将集合的成员强制转换为特定类(或接口)
IPlate aSmallPlate=(小板)板[1];
//然后你将获得混凝土类而无需再次浇铸
FalafelWaffle-aFalafel=aSmallPlate.GetMyWaffle();
Console.WriteLine(aFalafel.Dinner());
}
}
现在,.NET Framework 3.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());
    }
}
使用系统;
使用System.Collections.Generic;
公共接口IWaffle{string Eat();}
//在本例中,我定义了这个非泛型的额外接口
//在它里面,我们需要一种新的方法,相当于泛型方法
公共接口IPlateNG{IWaffle GetWaffle();}
//使泛型实现非泛型
公共接口IPlate:IPlateNG其中T:IWaffle{T GetMyWaffle();}
公共类BelgiumWaffle:IWaffle{
公共字符串Eat(){返回“吃比利时华夫饼”;}
公共字符串早餐(){return“早餐吃比利时华夫饼”;}
}
公共级法拉费华夫饼干:IWaffle{
公共字符串Eat(){return“吃法拉菲尔华夫饼”;}
公共字符串Dinner(){return“H
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()));
    }
}
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());
    }
}
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());
    }
}