与对象List <ianotherinterface>的接口 - 这可能吗?</ianotherinterface>

时间:2012-10-04 20:54:07

标签: c# interface

是否可以定义一个接口,其中一个对象是另一个接口的列表?

我有两个EF对象:

=====

class ImageType1
{
    string Id
    string Name
    List<ImageType1Size> Sizes
}

class ImageType1Size
{
    string Id
    int Width
    int Height
}

class ImageType2
{
    string UserId
    string ImageId
    string Name
    List<ImageType2Size> Sizes
}

class ImageType2Size
{
    string UserId
    string ImageId
    int Width
    int Height
}

=====

对于每个图像大小类,所有属性都是键(只是旁注)。

现在,我想要做的是创建以下两个接口:

=====

interface IImage
{
    string Name
    List<ImageSize> Sizes
}

interface IImageSize
{
    int Width
    int Height
}

=====

在我的项目中,我为ImageType1,ImageType1Size,ImageType2和ImageType2Size创建了部分内容,每个部分使用相应的界面。

我在尝试在ImageType1和ImageType2中强制转换Sizes属性以使用接口IImageSize时遇到错误。

=====

这可能吗?如果我不清楚请告诉我,我会重新解释这个问题。

谢谢!

6 个答案:

答案 0 :(得分:2)

您可能需要在此处考虑泛型:

interface IImage<TSize> where TSize : IImageSize
{
    List<TSize> Sizes { get; }
}

class ImageType1 : IImage<ImageType1Size>
{
    List<ImageType1Size> Sizes { get; private set; }
}

或者,这可行:

interface IImage
{
    IEnumerable<IImageSize> Sizes { get; }
}

class ImageType1
{
    public List<ImageType1Size> SizeList { get; private set; }

    public IEnumerable<IImageSize> Sizes { get { return SizeList; } }
}

这取决于您如何操作数据的最佳方式。

答案 1 :(得分:0)

由于ImageType1类的签名强制ImageType1.Sizes只包含ImageType1Size对象,因此不允许在ImageType1.Sizes中存储IImageSize,因为这样可以将非ImageType1Size对象(例如ImageType2Size)添加到名单。

这意味着您无法在ImageType1.Sizes中存储任何旧的IImageSize,这可能是您想要的。

但是,在执行其他操作时,您仍然可以使用ImageSize1和ImageSize2对象,就像它们是IImageSizes一样,例如

void Test()
{
    ImageType2 image = new ImageType2();
...
    foreach(var size in image.Sizes)
    {
        if(IsTooBig(size))
        {
            MessageBox.Show("I'm too big!")l
        }
    }
}

bool IsTooBig(IImageSize imagesize)
{
    return imagesize.Width > 500;
}

现在您可以在ImageType1Size和ImageType2Size对象上使用IsTooBig。

答案 2 :(得分:0)

之前有关于将List列入List的整个讨论。

你可以在这里阅读它,但它的要点是你不能用C#来做。

C# - Cannot implicitly convert type List<Product> to List<IProduct>

答案 3 :(得分:0)

foreach (IImageSize iSize in list) { int iWid = iSize.Width; }

答案 4 :(得分:0)

要构建default.kramer所说的内容,如果你明确需要IImage作为其他类型的类型,你可以像这样分割界面:

interface IImage
{
  string Name
}
interface IImage<TSize> : IImage where TSize : IImageSize
{
    List<TSize> Sizes { get; }
}

class ImageType1 : IImage<ImageType1Size>
{
    List<ImageType1Size> Sizes { get; private set; }
}

如果不这样做,如果没有指定IImage,就永远不会有TSize。当然,如果您需要能够访问非通用Sizes的{​​{1}}属性,则需要添加如下扩展方法:

IImage

答案 5 :(得分:0)

不幸的是,这不可能。在推理原因时,在界面之外考虑问题是有帮助的。

public void Example()
{
  List<ImageType1Size> Sizes1 = new List<ImageType1Size>();
  List<ImageType2Size> Sizes2 = new List<ImageType2Size>();
  List<IImageSize> Sizes;

  Sizes1 = Sizes; // These won't compile because the compiler can't guarantee that an
  Sizes2 = Sizes; // IImageSize is an ImageType1Size. It could be an ImageType2Size

  Sizes = Sizes1; // These will compile because the compiler knows that both 
  Sizes = Sizes2; // ImageType1Size and ImageType2Size are IImageSize's
}

现在您可以将它与您的课程进行比较。

class ImageType1 : IImageType
{
  string Id {get; set;}
  string Name {get; set;}
  List<ImageType1Size> Sizes {get; set;} // This is just like Sizes1 = Sizes in the
                                         // example above.
}

public void Test(IImageSize imageSize)
{
  IImageType imageType = new ImageType1();

  imageType.Add(imageSize) // This would compile, as IImageType.Sizes will 
                           // take any IImageSize

  // But what really happens behind the interface is this:
  ((ImageType1)imageType)Sizes.Add(imageSize);    

  // Trying to insert an IImageSize into the collection
  // doesn't work, because the compiler can't guarantee that 
  // it's an ImageType1Size
}

注意:我假设您的示例显示

interface IImage
{
  string Name
  List<ImageSize> Sizes
}

实际上应该是

interface IImage
{
  string Name
  List<IImageSize> Sizes
}

你没有在其他地方提到“ImageSize”类型。