【问题标题】:Why am I getting error: "cannot implicitly convert type System.Collections.Generic.List"为什么我收到错误:“无法隐式转换类型 System.Collections.Generic.List”
【发布时间】:2013-05-05 20:20:51
【问题描述】:

我有以下密封类。我正在尝试将列表作为ReadOnlyCollection 返回。尝试了几件事,但我不明白这一点。那么如何将列表返回或强制转换为只读集合?

    public sealed class UserValues
    {
        private readonly List<UserValue> _Values = new List<UserValue>();

        public ReadOnlyCollection<UserValues> Values
        {
            get
            {
                return _Values;
            }
        }
    }

【问题讨论】:

  • List&lt;UserValue&gt;object 作为它的基类。因此,ReadOnlyCollection&lt;UserValue&gt; 类不是基类,并且由于未定义隐式运算符,因此您不能像那样在这两个类之间进行转换。如果要创建新的ReadOnlyCollection&lt;&gt;,请使用_Values.AsReadOnly()。如果你使用最新的.NET版本(4.5,VS2012),可以将属性类型改为接口IReadOnlyList&lt;UserType&gt;。由于List&lt;&gt; 实现了IReadOnlyList&lt;&gt;,因此不需要强制转换。它没有那么安全(如果您不信任您班级的消费者)。
  • 一个坚定的消费者也可以使用反射来获取由ReadOnlyCollection&lt;T&gt; 包裹的IList&lt;T&gt;,但是,如果有人弄乱你的类的内部,你无能为力真的,真的很想。我想如果他们决心破坏事物,他们会找到办法的,所以不必太担心。
  • 我尝试像 Jeppe 提到的那样做 _Values.AsReadOnly() 并得到完全相同的编译器错误。而且我只用vs2008,所以无法访问他提到的界面。

标签: c# readonly-collection


【解决方案1】:

您会收到编译时错误,因为 List&lt;UserValue&gt; 不是 ReadOnlyCollection&lt;UserValue&gt;,也不能隐式转换为。 (顺便说一下,我假设您的意思是 ReadOnlyCollection&lt;UserValue&gt; 而不是 ReadOnlyCollection&lt;UserValues&gt;?)

使用List&lt;T&gt;.AsReadOnly 可能是最简单的——但您也可以只创建一次:

public sealed class UserValues
{
    private readonly List<UserValue> values = new List<UserValue>();
    private readonly ReadOnlyCollection<UserValue> valuesView;

    public UserValues()
    {
        valuesView = values.AsReadOnly();
    }

    public ReadOnlyCollection<UserValues> Values { get { return valuesView; } }
}

ReadOnlyCollection&lt;T&gt; 确实只是一个视图 - 因此对基础集合的更改将通过视图可见。

【讨论】:

  • 嗨乔恩。不,我确实是指带有 s 的“UserValues”。我的主管给了我代码存根,我应该在不更改方法签名的情况下填写它们。如果我可以更改签名以匹配变量,这将容易得多。
  • @Debbie:那么您在问题中编写的代码几乎没有意义。你确定不是笔误?我建议你问问你的主管。 UserValues 类拥有UserValue 对象的集合是有意义的,但对于它来说拥有UserValues 对象的集合是不合理的。
【解决方案2】:

试试:

return new ReadOnlyCollection<UserValue>(_Values);

编辑:

鉴于您对 Jon 所说的话,您的代码没有意义。您的 get 引用了 List&lt;UserValue&gt; 的类型,但您希望将其转换为 ReadOnlyCollection&lt;UserValues&gt; 的类型,这是无法完成的 - 这是 2 个不同类型的 2 个集合。

我们需要更多信息来帮助您回答这个问题。您是否希望您的 UserValues 类返回 UserValues 类型的集合或 UserValue 类型的集合?您的代码暗示 UserValue,但您关注 cmets 状态 UserValues。你确定你的主管没有打错字吗?

如果没有,您将需要一些像这样的内部集合:

private readonly List<UserValues> _MoreValues = new List<UserValues>();

然后以我(或其他已回答的人 - 所有给出的答案对于将 List 转换为 ReadOnlyCollection 的有效)显示的语法返回。

请注意,我的代码编译目标是 .Net 3.5,假设类型是兼容的(意思是 ReadOnlyCollection&lt;UserValue&gt; 包装 List&lt;UserValue&gt;,或两者都是 UserValues)。

【讨论】:

  • 这将在每次访问属性时创建一个 ReadOnlyCollection&lt;T&gt; 包装器的新实例——可能并不理想。
  • 确实它不是“理想的”,但在这种情况下,它回答了问题并让提问者上路。您可以按照其他人的建议执行 .AsReadOnly,但是如果您反编译它,您会看到它这样做:return new ReadOnlyCollection((IList) this);。 “最佳”解决方案(取决于人的需要)是创建一个持有只读集合的​​成员,然后返回它......但这似乎超出了问题的范围,这是一个铸造问题。
  • 我刚刚有时间尝试上面的代码,它也不会编译。
  • 不,我的代码可以编译(它现在可以在我的机器上的 VS2012 中编译),但是当您将其更改为 &lt;UserValues&gt; 类型时它不会编译,这就是您的在你对乔恩的评论中说你需要。我会在我的回答中添加更多想法......
【解决方案3】:

_ValuesList&lt;UserValue&gt;,而不是ReadOnlyCollection&lt;UserValue&gt;(就编译器所知,它们不相关),因此您不能直接返回_Values。您可以从您的列表中创建一个ReadOnlyCollection&lt;T&gt; 并将其返回,例如:

private List<UserValue> _Values = [whatever];
private ReadOnlyCollection<UserValue> _ValuesWrapper;

public UserValues()
{
  _ValuesWrapper = _Values.AsReadOnly();
}

public ReadOnlyCollection<UserValue> Values
{
  get { return _ValuesWrapper; }
}

...或者,如果您只是在寻找一种只读方式来访问您的集合并且不需要专门的 ReadOnlyCollection&lt;UserValue&gt; 对象,您可以更改您的属性以返回一个只读接口 @ 987654329@ 实现,您的应用程序可以使用它。 .NET 4.5 引入了一些只读的集合接口,这些接口对于这类事情非常棒

public IReadOnlyList<UserValue> Values
{
  get { return _Values; }
}

【讨论】:

  • 遗憾的是,我无法访问 .net 4.5。我的 Visual Studio 是 2008。到目前为止,这里提到的任何内容都不适用于我拥有的 Visual Studio 版本。任何人都可以“简化”他们从 .net 4.5 到 .net 3.5 的回复吗?
  • 我的代码编译目标是 .Net 3.5。此外,Jeremy 和 Jon 推荐的 .AsReadOnly() 从 .Net 2.0 开始就得到支持,所以他们的也可以编译 (msdn.microsoft.com/en-us/library/e78dcd75(v=vs.90).aspx)。问题在于您需要包装 UserValue 集合类的 UserValues 只读集合。请提供我在回答中提到的更多信息,以帮助我们回答您的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多