代码之家  ›  专栏  ›  技术社区  ›  Matt Mitchell

“Force-casting” a returned type

  •  2
  • Matt Mitchell  · 技术社区  · 14 年前

    This should be a pretty trivial one.

    Can C# return a type that is "force-cast", that is where the following 失败 :

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

    I'm aware I could do this:

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

    但这似乎(1)是不必要的,(2)仍然不阻止他们投射到一个记忆中,只是为了增加和(3)我只是对一般问题很好奇。

    澄清

    有些人似乎不确定我在这里想要达到什么目标。我正在努力防止外部课程违反我提供的合同。我并没有说过字符串是一个集合——它正好是我在内部使用的,因此,没有外部类应该能够将返回的变量当作一个集合。我不想把修改行为暴露给他们,我不希望他们把我的变量当作一个集合,以防后来我改变了iQueDebug的生成方式。

    更一般地说,我可以返回一个对象作为它的一个更具体类型的实例,并防止以后强制转换为它的一个更一般的类型。例如,虽然您可以生成一个新的IEnumerable,但是您是否可以返回一个IDisposable对象,该对象不能被强制转换回它是什么类型(即只有dispose()和object方法可调用)?

    3 回复  |  直到 14 年前
        1
  •  5
  •   Thomas Levesque    14 年前

    Ah ok, I see what you mean now...

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

    But it has nothing to do with boxing...

        2
  •  5
  •   Community CDub    7 年前

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

    That being said, there is no "general purpose" way to prevent users from attempting to cast types to their "actual" type instead of an interface you provide them.

    The closest thing you can do is use types that are internal within your assembly, and not visible to the caller. This will prevent the user from being able to use your type directly (at least without resorting to reflection in elevated trust situations).

    不过,总的来说,我建议不要担心这一点。任何将您的类型强制转换为未记录的内部实现细节类型的用户都只是在自找麻烦,我不会尝试用代码来防止这种情况发生。这样做只会对您自己造成损害,因为您正在降低代码的可维护性。

        3
  •  1
  •   sepp2k    14 年前

    In this specific case where you return an IEnumerable Thomas's solution using yield is probably the best. In the general case where the returned interface might be anything (like IDisposable as you mentioned in your edit) the only way to achieve what you want would be to create a wrapper class that implements the given interface using delegation (e.g. a class MyDisposable that holds an IDisposable and implements the Dispose method by calling Dispose on the IDisposable it holds).