“强制转换”返回类型

时间:2010-06-26 18:25:58

标签: c# types

这应该是一个非常微不足道的。

C#可以返回“强制转换”类型,即以下 失败

 private ICollection<string> _strings = new List<string>();
 public IEnumerable<string> Strings
 {
     get
     {
          return ((IEnumerable<string>)_strings);
     }
 }

 /* I should not know that Strings can be cast to ICollection */
 public void AddToStrings()
 {
     ICollection<string> st = ((ICollection<string>)Strings); /* I should fail */
     st.Add("MyString");
 }

我知道我可以这样做:

 public IEnumerable<string> Strings
 {
     get
     {
          return ((IEnumerable<string>)_strings.ToArray());
     }
 }

但这似乎是(1)不必要的,(2)仍然没有阻止他们转向ICollection,只是添加和(3)我只是对一般问题感到好奇。

澄清

有些人似乎不确定我在这里想要达到的目标。我试图阻止外部课程违反我提供的合同。我没有说过Strings是一个ICollection - 它恰好发生在我内部使用它 - 因此没有外部类应该能够将我返回的变量视为ICollection。我不想向他们公开修改行为,我不希望他们将我的变量视为ICollection,以防我后来改变生成IEnumerable的方式。

更一般地说,我可以将对象作为其特定类型之一的实例返回,并防止以后转换为其更常规类型之一。例如,虽然你可以产生一个新的IEnumerable,你能否返回一个IDisposable对象,它不能被转换回它的任何类型(即只有Dispose()和对象方法可调用)?

3 个答案:

答案 0 :(得分:5)

好的,我明白你的意思了......

 public IEnumerable<string> Strings
 {
     get
     {
          foreach (var s in _strings) yield return s;
     }
 }

但它与拳击无关......

答案 1 :(得分:5)

Thomas为这个特定的例子提供了正确的答案。

话虽如此,没有“通用”方法来阻止用户尝试将类型转换为“实际”类型而不是您提供的接口。

您可以做的最接近的事情是使用程序集内部的类型,并且对调用者不可见。这将阻止用户直接使用您的类型(至少在高架信任情况下不采用反射)。

但是,总的来说,我建议不要担心这一点。将您的类型转换为未记录的内部实现细节类型的任何用户只是在寻找麻烦,我不会尝试编写一种防止这种情况的方法。这样做只会让你自己受到伤害,因为你的代码不易维护。

答案 2 :(得分:1)

在这种特殊情况下,使用yield返回IEnumerable Thomas的解决方案可能是最好的。在返回接口可能是任何东西的一般情况下(如您在编辑中提到的IDisposable),实现您想要的唯一方法是创建一个使用委托实现给定接口的包装类(例如,一个类MyDisposable,它包含一个IDisposable并通过调用它所持有的IDisposable上的Dispose来实现Dispose方法。