1

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

我有两个 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 时遇到错误。

=====

这可能吗?如果我不清楚,请告诉我,我会改写问题。

谢谢!

4

6 回答 6

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; } }
}

这取决于最适合您操作数据的方式。

于 2012-10-04T21:17:06.343 回答
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”类型一样。

于 2012-10-04T21:30:25.703 回答
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. 当然,如果您需要能够访问Sizesnon-generic 的属性IImage,您将需要添加这样的扩展方法:

static class IImageHelper
{
  static List<IImageSize> GetSizes<TSize>(this IImage<TSize> image) where TSize: IImageSize
  {
    return image.Sizes.OfType<IImageSize>();
  }
}
于 2012-10-04T21:26:59.900 回答
0

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

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

但是,您仍然可以在执行其他操作时使用 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。

于 2012-10-04T21:09:58.467 回答
0

之前有一个关于将 List 转换为 List 的完整讨论。

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

C# - 无法将类型 List<Product> 隐式转换为 List<IProduct>

于 2012-10-04T21:13:09.510 回答
0

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

于 2012-10-04T21:16:56.013 回答