【问题标题】:Access internal interfaces inside owner class访问所有者类中的内部接口
【发布时间】:2023-03-13 19:11:01
【问题描述】:

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

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

我不介意我只在代码中使用一次该转换,但事实并非如此。我在代码中有 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;
    }
}

【问题讨论】:

  • 请注意,声明接口的约定意味着您应该将其命名为IKey,或者甚至可能是IKeyable
  • @EvanTrimboli 谢谢,我会记住这一点的。
  • 对 Foo 中的 Obj 的访问修饰符丢失。默认是私有的
  • 这里没有访问修饰符。试试看。
  • 为了隐式实现接口方法/属性必须是公共非静态Interfaces (C# Programming Guide)

标签: c#


【解决方案1】:

您将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 不起作用。

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


编辑后

完全不同的情况:

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

【讨论】:

  • 我没有两个 ID 属性。我有一个实现内部接口的公共类,编译器强制我使用显式实现,但为什么呢?整数 ID { 获取; set } 不起作用,但 int iKey.ID { get;放; } 工作。那么为什么在使用内部接口时使用显式方式呢?
  • 你在某处得出了错误的结论。 public class 可以隐式实现 internal interface。那里没问题。
  • 提示:编写一个小型、独立的项目来展示您的问题。完整的代码应少于 20 行且可发布。
  • internal class Poco 是这里大多数问题的根源。
  • 那么 Foo 也必须是internal。或者将Poco 包裹在公共接口IPoco 中。
【解决方案2】:

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

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

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

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

【讨论】:

  • 很高兴知道这一点。谢谢!
【解决方案3】:

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

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

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

这是一个有效实现的示例:

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

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

关于问题编辑:

有几件事不适用于该场景:

  1. Foo 类的 Obj 属性(默认情况下)是私有的,因此无论有无接口,它都无法在类外部访问。
  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;}
}

【讨论】:

  • +1 表示“如果您有两个具有相同名称的方法的接口,这将非常有用。” - 无需更多解释
  • 那么你想达到什么目的?使属性在程序集之外不可见并实现内部接口?那么,如果您想直接访问它,为什么需要该接口?为什么不使用公共接口来允许从程序集外部访问公共功能?你不是想在一种类型中合并不同的职责吗?
  • @devhedgehog 这比简单地找到正确的访问器更复杂:)
  • 是的,我想让一个属性不可见并实现内部接口。我需要接口,因为很少有类会实现它,后来我只是转换为接口,我不需要每次都询问什么类型的类,因为我只需要类中的 Obj 属性
【解决方案4】:

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

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 指定访问修饰符,这使它成为私有的。

【讨论】:

  • 有趣..让我检查一下
  • 你不能有访问修饰符。那就是问题所在。试试看。他们都没有工作。不是公开的、私人的或内部的。
  • 接口成员实现必须是公开的或显式的。此外,您不能为显式实现的接口指定任何访问修饰符。
  • 我不需要。接口应留在内部。没有人可以看到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 2022-08-15
  • 1970-01-01
  • 2011-02-17
  • 2014-08-24
相关资源
最近更新 更多