如何返回 Collection作为集合<接口>?接口>
我有一个具体类,其中包含另一个具体类的集合。我想通过接口公开这两个类,但我无法弄清楚如何将 Collection
我当前正在使用 .NET 2.0
下面的代码会导致编译器错误:
无法隐式转换类型 'System.Collections.ObjectModel.Collection
''到 'System.Collections.ObjectModel.Collection '
注释的尝试强制转换给出了此编译器错误:
无法转换类型 'System.Collections.ObjectModel.Collection
''到
'System.Collections.ObjectModel.Collection'通过一个 引用转换、装箱转换、拆箱转换、包装 转换,或 null 类型转换。
有没有办法将具体类型的集合公开为接口集合,或者我是否需要在接口的 getter 方法中创建一个新集合?
using System.Collections.ObjectModel;
public interface IBucket
{
Collection<INail> Nails
{
get;
}
}
public interface INail
{
}
internal sealed class Nail : INail
{
}
internal sealed class Bucket : IBucket
{
private Collection<Nail> nails;
Collection<INail> IBucket.Nails
{
get
{
//return (nails as Collection<INail>);
return nails;
}
}
public Bucket()
{
this.nails = new Collection<Nail>();
}
}
I have a concrete class that contains a collection of another concrete class. I would like to expose both classes via interfaces, but I am having trouble figuring out how I can expose the Collection<ConcreteType> member as a Collection<Interface> member.
I am currently using .NET 2.0
The code below results in a compiler error:
Cannot implicitly convert type
'System.Collections.ObjectModel.Collection<Nail>' to
'System.Collections.ObjectModel.Collection<INail>'
The commented attempt to cast give this compiler error:
Cannot convert type
'System.Collections.ObjectModel.Collection<Nail>' to
'System.Collections.ObjectModel.Collection<INail>' via a
reference conversion, boxing conversion, unboxing conversion, wrapping
conversion, or null type conversion.
Is there any way to expose the collection of concrete types as a collection of interfaces or do I need to create a new collection in the getter method of the interface?
using System.Collections.ObjectModel;
public interface IBucket
{
Collection<INail> Nails
{
get;
}
}
public interface INail
{
}
internal sealed class Nail : INail
{
}
internal sealed class Bucket : IBucket
{
private Collection<Nail> nails;
Collection<INail> IBucket.Nails
{
get
{
//return (nails as Collection<INail>);
return nails;
}
}
public Bucket()
{
this.nails = new Collection<Nail>();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
C# 3.0 泛型是不变的。如果不创建一个新对象,就无法做到这一点。 C# 4.0 引入了安全协变/逆变,无论如何它都不会改变读/写集合(您的情况)的任何内容。
C# 3.0 generics are invariant. You can't do that without creating a new object. C# 4.0 introduces safe covariance/contravariance which won't change anything about read/write collections (your case) anyway.
只需将指甲定义为
Just define nails as
为什么不只是将其作为接口返回,只需将所有公共方法都放在接口中,这样就不会出现此问题,而且,如果您稍后决定返回另一种类型的 Nail 类,那么它会正常工作。
Why not just return it as an interface, just have all your public methods in the interface, that way you don't have this problem, and, if you later decide to return another type of Nail class then it would work fine.
您使用什么版本的.Net?
如果您使用 .net 3.0+,则只能通过使用 System.Linq 来实现此目的。
查看这个问题,它为我解决了这个问题。
What version of .Net are you using?
If you are using .net 3.0+, you can only achieve this by using System.Linq.
Check out this question, which solved it for me.
有一种解决方案可能不完全符合您的要求,但可能是一种可接受的替代方案 - 使用数组代替。
(如果您最终执行了类似的操作,请记住此框架设计指南注释:通常不应将数组公开为属性,因为它们通常在返回给调用者之前进行复制,并且在数组内部执行复制是一项昂贵的操作无辜财产得到。)
There is one solution that might not be quite what you are asking for but could be an acceptable alternative -- use arrays instead.
(If you end up doing something like this, keep in mind this Framework Design Guidelines note: generally arrays shouldn't be exposed as properties, since they are typically copied before being returned to the caller and copying is an expensive operation to do inside an innocent property get.)
使用它作为你的属性获取器的主体:
这是一个有点老套的解决方案,但它可以满足你的要求。
编辑以返回 ReadOnlyCollection。确保更新 IBucket 和 Bucket 中的类型。
use this as the body of your property getter:
That is a tad bit of a hacky solution but it does what you want.
Edited to return a ReadOnlyCollection. Make sure to update your types in IBucket and Bucket.
您可以添加一些泛型。更适合,耦合更紧密。
这样,从
Bucket
类返回的Collection
只能保存Nail
。任何其他Iail
都不会进入其中。这可能会更好,也可能不会更好,具体取决于您想要什么。仅当您希望从
Bucket
返回的Collection
(接口属性)来保存其他INail
(而非Nail< /code>s) 那么你可以尝试下面的方法。但有一个问题。一方面,您说您想在
Bucket
类中使用private Collection
而不是Collection
因为您不希望意外地将Bucket
类中的其他INail
添加到其中,但另一方面,您必须从外部添加其他
类。 在同一个实例上这是不可能的。编译器会阻止您意外地将任何INail
>BucketINail
添加到Collection
中。一种方法是从现有Collection
的Bucket
类返回不同的Collection
实例。这效率较低,但可能就是您所追求的语义。 请注意,这在概念上与上面不同You can add some generics. Fits better, more strongly coupled.
This way the
Collection<Nail>
you return fromBucket
class can only ever holdNail
s. Any otherINail
wont go into it. This may or may not be better depending on what you want.Only if you want
Collection<INail>
(the interface property) you return fromBucket
to hold otherINail
s (thanNail
s) then you may try the below approach. But there is a problem. On one side you say you want to use aprivate Collection<Nail>
inBucket
class and not aCollection<INail>
because you dont want to accidentally add otherINail
s fromBucket
class into it but on the other side you will have to add otherINail
s from outside ofBucket
class. This is not possible on the same instance. Compiler stops you from accidentally adding anyINail
to aCollection<Nail>
. One way is to return a different instance ofCollection<INail>
from yourBucket
class from the existingCollection<Nail>
. This is less efficient, but could be the semantics you are after. Note that this is conceptually different from aboveC# 不支持泛型集合协方差(仅支持数组)。
在这种情况下我使用适配器类。它只是将所有调用重定向到实际集合,将值转换为所需的类型(不需要将所有列表值复制到新集合)。
用法如下:
C# doesn't support generic collections covariance (it's only supported for arrays).
I use an adapter class in such cases. It just redirects all calls to the actual collection, converting values to the required type (doesn't require copying all list values to the new collection).
Usage looks like this:
你可以使用 Cast 扩展,
我无法在这里测试它来提供更全面的示例,因为我们在工作中使用 .NET 2.0(抱怨抱怨),但我确实有一个类似的问题 此处
you could use the Cast extension
I can't test it here to provide a more comprehensive example, as we are using .NET 2.0 at work (gripe gripe), but I did have a similar question here