是否可以定义一个接口,其中一个对象是另一个接口的列表?
我有两个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时遇到错误。
=====
这可能吗?如果我不清楚请告诉我,我会重新解释这个问题。
谢谢!
答案 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”类型。