C# 中的类层次结构:如何正确执行? (想要“朋友”关键字)

发布于 2024-09-25 05:23:21 字数 442 浏览 6 评论 0原文

我有一堂课:

public class MyClass {  
 private List<string> folderList;  
 // .... a lot of useful public methods here.....  
}  

一切都很好。文件夹列表是封装的,该类可以通过公共方法访问。好的。现在我需要一个“选项”表单,允许用户为 MyClass 选择文件夹。有一个问题:新的安装类必须有权访问私有folderList字段(或者我必须提供公共方法来获取和设置文件夹列表 - 本质上是相同的)。在旧的好的 C++ 中,我会使用“friend”功能,因为除了安装类之外没有人可以访问folderList。但 C# 中没有“朋友”功能(我是 C# 世界的新手)。

PS 其实我只是公开了folderList,但我觉得有更好的解决方案。

谢谢。

I have a class:

public class MyClass {  
 private List<string> folderList;  
 // .... a lot of useful public methods here.....  
}  

Everything is fine. The list of folders is encapsulated, the class is accessible through public methods. OK. Now I need an "options" form that allows a user to choose folders for MyClass. There is a catch: new Setup class must have access to private folderList field (or I have to provide public methods to get and set the folder list - it's essentially the same). In old good C++ I would use 'friend' feature because nobody but Setup class may access folderList. But there is no 'friend' feature in C# (I'm a newbie in the C# world).

P.S. Actually I just made folderList public, but I feel there is a better solution.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

澜川若宁 2024-10-02 05:23:21

您可以使用“internal”关键字使您的方法仅在程序集/项目中可用,如果您想访问其他项目或程序集中的内部方法,则可以使用“InternalsVisibleTo”属性,您只能在该属性中访问内部方法您为其定义此属性的程序集。

MSDN 内部关键字

You can use "internal" keyword to make your method available only within your assembly/project and if you want to access your internal methods in other project or assembly then you can use "InternalsVisibleTo" attribute, where you can access your internals only in that assembly for which you define this attribute.

MSDN Internal Keyword

输什么也不输骨气 2024-10-02 05:23:21

我相信您正在寻找的关键字是internal。它大致相当于 C++ 的 friend

Internal 提供程序集级别的可见性。

结合 Femaref 使用属性的建议,您应该拥有完整的解决方案。

I believe the keyword you're looking for is internal. It is loosely equivilent to C++'s friend.

Internal provides assembly-level visibility.

Paired with Femaref's suggestion of using a Property, and you should have your full solution.

微凉 2024-10-02 05:23:21

我不确定这是否是他/她想要的。他/她没有提出潜在客户将在当前程序集中的要求...因此,在 C++ 中使用 friend 时(这从来不被认为是一种好的风格),您必须知道 有权访问成员的类的确切类型。如果此类不是您正在编写的程序的一部分,则无法以这种方式授予访问权限。

如果您想要有条件地访问类实例的某些属性或方法,则需要实现某种权利机制,例如:

public IList<Folder> GetFolderList(Object pClient, IEntitlementService pService) {
 if (pService.IsEntitledToAccess(this, pClient) {
  return folderList;
 } else {
  throw new AccessNotGrantedException("...");
 }
}

我相信 .Net 框架中有内置实用程序用于此目的,只需执行和谷歌(或必应)...

I am not sure if this is what he/she wanted. He/she did not put the requirement that the potential client will be in current assembly... Accordingly, when using friend in c++ (which was never considered a good style) you must know the exact type of the class which will be entitled to access the member. If this class is not part of the program you are writing, you cannot grant access this way.

If you want conditional access to some property or method of an instance of a class, you will need to implement some kind of entitlement mechanism, for example:

public IList<Folder> GetFolderList(Object pClient, IEntitlementService pService) {
 if (pService.IsEntitledToAccess(this, pClient) {
  return folderList;
 } else {
  throw new AccessNotGrantedException("...");
 }
}

I believe there are built-in utilities in the .Net framwork for that purpose, just go and google (or bing)...

久隐师 2024-10-02 05:23:21

作为问题的确切答案,我建议如下 - 创建一个单独的接口 IFolderList:

interface IFolderList
{
  IList<string> FolderList { get; }
  ...
}

好吧,您可以将其他必需的成员添加到接口

中 在类 MyClass 中显式实现此接口。

因此,Setup 类可以通过显式转换为接口 IFolderList 来访问数据,或者仅使用这些接口。

As an exact answer to the question I would suggest the following - create a separate interface IFolderList:

interface IFolderList
{
  IList<string> FolderList { get; }
  ...
}

Well, you can add other required members to interface

In the class MyClass implement this interface explicitly.

As a result, the class Setup can gain access to data through an explicit cast to an interface IFolderList or work only with these interface.

不美如何 2024-10-02 05:23:21

使 Setup 类使用 internal 方法的另一种方法是使用 Visitor 模式并添加一个采用 Setup 类实例作为参数的方法,然后使用私有 folderList 根据需要初始化/更改 Setup 状态。当然,这需要 Setup 类上的适当公共方法,因此可能不适合您的需求。

An alternative to making an internal method to be used by your Setup class would be to use the Visitor pattern and add a method that takes a Setup class instance as a parameter, then uses the private folderList to initialize/change Setup state as required. Of course that would require the appropriate public methods on the Setup class, so might not fit your needs.

初熏 2024-10-02 05:23:21

folderList 字段公开是最坏的情况。通过公共字段或通过设计不良的公共属性暴露实现细节(公共字段和具有 getter 和 setter 的公共属性之间的集合没有区别)。

对于公共字段,当您想要添加验证、更改通知、将其放入界面或将集合类型从一种类型更改为另一种类型时,您无法将字段提升为属性。

顺便说一句,Jeffrey Richter 在框架设计指南的注释中提到,“就个人而言,我总是将我的字段设为私有。我什至不将字段公开为内部,因为这样做不会给我任何保护来自我自己的程序集中的代码”

我认为添加向 MyClass 客户端公开严格抽象的显式接口的最佳方法。

例如,您可以添加两个单独的方法来检索文件夹并将新文件夹添加到此存储:

class MyClass {
  //You should return IList<string>
  public IList<string> MyList {get {return myList;} }

  //Or even IEnumerable<string>, because you should return
  //as minimal interface as your clients needs
  public IEnumerable<string> MyList {get {return myList;} }

  //You may expose this functionality through internal
  //method, or through protected internal method,
  //but you should avoid direct access to your implementation
  //even for descendants or another classes in your assembly
  public void AddElement(string s) {myList.Add(s);}

  private List<string> myList;
}

Making folderList field public is the worst case. Exposing implementation details through public fields or through poorly designed public property (there are no differences for collections between public fields and public property with getter and setter).

With public fields you can't promote a field to be a property when you want to add validation, change notification, put it into an interface or change your collection type from one type to another.

BTW, Jeffrey Richter in annotation to Framework Design Guideline mentioned that "Personally, I always make my fields private. I don't even expose fields as internal, because doing so would give me no protection from code in my own assembly"

I think the best way to add explicit interface that expose strict abstraction to MyClass clients.

For example, you may add two separate methods to retrieving folders and to adding new folder to this storage:

class MyClass {
  //You should return IList<string>
  public IList<string> MyList {get {return myList;} }

  //Or even IEnumerable<string>, because you should return
  //as minimal interface as your clients needs
  public IEnumerable<string> MyList {get {return myList;} }

  //You may expose this functionality through internal
  //method, or through protected internal method,
  //but you should avoid direct access to your implementation
  //even for descendants or another classes in your assembly
  public void AddElement(string s) {myList.Add(s);}

  private List<string> myList;
}
时光瘦了 2024-10-02 05:23:21

这就是属性在 C# 中的作用:

public class MyClass 
{
  private List folderList;

  public List FolderList
  {
    get {return folderList;}
    set {folderList = value;}
  }
}

属性封装私有字段,提供设置时验证的可能性。另外,您应该阅读泛型(有点像 C++ 中的模板)并使用 List 而不是 List 来拥有强类型集合。

但是,除非 Setup 派生自 MyClass,否则您可能无法实现您的计划。在这种情况下,您可以使用protected 字段。

That's what properties are for in C#:

public class MyClass 
{
  private List folderList;

  public List FolderList
  {
    get {return folderList;}
    set {folderList = value;}
  }
}

Properties encapsulate the private fields, provide possibilites for validation while setting. Also, you should read up on Generics (abit like templates in c++) and use List<T> instead of List to have a strongly typed collection.

However, you probably wont be able to achieve what you plan unless Setup derives from MyClass. In that case, you can use a protected field.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文