1

我有一个内部接口。通常我使用公共接口,但这次我将很多东西保留在内部。

现在的问题是,当我在一个实现内部接口的公共类中,该接口还包含一个内部成员时,为什么我不能在不强制转换的情况下访问接口成员(显式实现)?我在“所有者”类里面,实现接口的类,完全在里面,我应该有所有的权利,对吧?

如果我只在代码中使用一次该转换,我不会介意,但事实并非如此。我在代码中有 10 次这样的星座。它有点烦人。

我错过了什么吗?就像我说的那样,我通常不使用内部接口。

在您开始投票或发布此问题如何重复之前,只需发表评论,我将删除它。

这是代码:

internal class Poco
{
    public string Str
    {
        get;
        set;
    }
}

internal interface ITest1
{
    Poco Obj
    {
        get;
        set;
    }
}

public class Foo : ITest1
{
    // Not working
    Poco Obj
    {
        get;
        set;
    }
}
4

4 回答 4

2

您可以拥有一个内部(甚至是私有)属性以及公开它的显式接口实现:

public class Foo : ITest1
{
    internal Poco Obj { get; set; }

    Poco ITest1.Obj { get { return Obj; } set { Obj = value; } }
}

这是“改变”界面成员可见性的推荐方式。许多 .NET 类使用这种技术将接口成员转换为protected virtual成员。

于 2013-10-08T08:59:37.620 回答
2

您将internal访问修饰符与接口的显式实现混淆了。

接口的事实internal与它在实现类中的可见性无关。它只限制对本地程序集的可见性。

显式实现允许名称冲突:

interface IKey1 { int ID { ... } }
interface IKey2 { int ID { ... } }

class MyOwnerClass : IKey1, IKey2  // requires explicit imp
{
  int IKey1.ID  {  ....  }
  int IKey2.ID  {  ....  }

  // the only way to access this:
  void Foo() 
  { 
     int i1 = ((IKey1)this).ID; 

     IKey2 ik2 = this;
     int i2 = ik2.ID; 

     int i3 = ID; // error, otherwise: which one
  }
}

您的核心问题:如何在不强制转换的情况下访问接口成员。在这个例子中,任何引用this.ID都是模棱两可的。

并且不允许隐式实现具有冲突成员的接口。

为什么private iKey.ID不工作。

编译器在这里控制可见性,并使其比“私有”更加隐藏。这类似于为什么你不能public在里面使用interface IA { ... }


编辑后

完全不同的情况:

internal class Poco { ... }     // this 'internal' is a problem 
internal interface ITest1       // this isn't
{ 
  Poco Obj  {  }                // Poco is an internal type
}

public class Foo : ITest1
{
    // Not working
    Poco Obj  { ... }          // property _and_ type need to be public
}

您试图在公共类上拥有一个公共属性,但属于内部类型。从程序集外部
查看:

 Foo f = ...;   // OK, Foo is a public Type
 f.Obj = ...;   // but we don't know the Type of Obj here
于 2013-10-08T07:45:27.703 回答
1

这正是规范中定义显式接口的方式。

“显式”部分的意思是“我将告诉代码何时将该对象视为接口”,因此除非您告诉代码(通过强制转换),否则它将看不到接口的方法/属性。如果您有两个具有同名方法的接口,这将非常有用。

您可以有一个内部接口,但您不能将它用于公共类(请参阅这篇文章了解一些原因)。

下面是一个有效实现的例子:

internal interface IKeyable
{
  int ID {get; set;}
}

internal class MyClass: IKeyable
{
  public int ID  { get; set; }
}

关于问题编辑:

有几件事不适用于这种情况:

  1. 类的Obj属性Foo(默认情况下)是私有的,因此无论有没有接口,它都不能在类外部访问。
  2. 因为接口中定义的所有成员都必须可以从类外部访问,所以Obj不被认为是接口实现的合适候选者ITest1
  3. 虽然Foo是公共的,但是Poco是内部的,这意味着即使用户(从程序集外部将能够访问该类,他将无法访问该属性,这是没有意义的。

如果你想向世界公开一个内部类(例如,公开它的数据,但不是它的内部细节),你可以创建一个公共访问接口,或者创建一个公共访问类,它知道转换到/从你的班。

所以你可以这样做:

public interface IPoco { 
   string Title {get; } //restring writing, for example
}

internal class Poco : IPoco
{
   public string Title {get; set; } //read/write access within the assembly
}

public class Foo 
{
   public IPoco MyPoco {get; set;}
}

或者

public class PocoAccessor
{
   public string Title {get; private set;}  
   internal static PocoAccessor ToPocoAccessor(Poco source)
   {
      return new PocoAccessor { Title = source.Title}
   }
}

public class Foo 
{
   public PocoAccessor MyPoco {get; set;}
}
于 2013-10-08T07:49:09.833 回答
0

您的属性仍然缺少类型。即使您想将其声明为接口成员的显式实现,您仍然需要指定类型。

class MyOwnerClass : iKey
{
    int id;

    int iKey.ID
    {
        get {return this.id;}
        set { this.id = value;}
    }
}

赋予接口 iKey 的“内部”访问修饰符只会使其在定义它的命名空间之外不可见。不多也不少。此外,正如有人指出的那样,更好的接口命名约定是使用描述预期功能集的形容词,前缀为“I”。

 internal class Poco
 {
   public string Str
   {
     get;
     set;
   }
}

internal interface ITest1
{
   Poco Obj
   {
     get;
     set;
   }
}

public class Foo : ITest1
{

   Poco Obj // missing access modifier
   {
     get;
     set;
   }
}

没有为 Obj 指定访问修饰符,这使其成为私有的。

于 2013-10-08T07:51:45.050 回答