百科问答小站 logo
百科问答小站 font logo



c#中没有友元类那么这种设计是否不太合理,如何修改才能得到更好的方案? 第1页

  

user avatar   Ivony 网友的相关建议: 
      

这是C#类型系统无法解决的问题。但是通常来说不那么追求洁癖的话也没什么太大的关系。

C#的友元只能到程序集的层面,没有类型层面上的友元。通常这种问题用internal interface解决(如果有继承关系也可以用protected interface),当然这个也没有办法细化到类型的级别,但一般够用。


顺便说一下什么叫做internal interface,这个要借助C#的一个特性,叫做显示接口实现。

显示接口实现有一个非常有用的特性,就是显示接口实现的成员其可见性等价于接口。这就带来一种手法:

       internal interface IFoo {   void SetName( string name ); }  public class MyClass : IFoo {   public Name { get; private set; }   void IFoo.SetName( string name ) => Name = name; }      

这样就使得,任何可以看到IFoo接口的类型,都可以调用SetName方法,而任何看不到IFoo接口的类型,都不能调用。


当然有人会说,为啥要这么麻烦?我直接写成这样不就好了?

         public Name { get; internal set; }      

这样的确可以,但是显示接口实现的好处在于更好的语义提示:

       public void ResetName( MyClass instance) =>   ((IFoo) instance).SetName( "" );      

这里的强转可以起到语义提示,我要干坏事了……



当然,未来C#里面会增加扩展属性(和扩展方法一样),到时候可以在很大程度上解决这个问题。当然不嫌丑的话,也可以用扩展方法解决。

要实现这一点,我们就必须把Equipment从Human剥离出来。然后用一个EquipmentContainer来管理这一个东西,很显然,当Equipment从Human剥离出来后,他的set的问题就被彻底解决了。因为很显然的,Human并没有设置Equipment,它本质上是被EquipAction所使用的。

在使用扩展方法的模式下,这会使得代码变得丑陋:

       internal sealed class EquipmentContainer {   public IEquipment Equipment{ get; set; } }  public static class EquipmentExtensions {   public static IEquipment GetEquipment( Human human )   {     return human.Features.Get<EquipmentContainer>().Equipment;// Features参考AspNetCore的设计。   }    internal static void SetEquipment( Human human, IEquipment equipment )   {     human.Features.Get<EquipmentContainer>().Equipment = equipment;   } }      

顺便说一下这个EquipmentContainer的意义在哪里,它的意义就在于,当你看不到这个类型的时候,你永远也没法给Human设置Equipment,如果我们不用这样一个中介而直接使用IEquipment,则因为Features方法是public的,导致任何人都可以设置Equipment




  

相关话题

  python是用C实现的,Java是用C++实现的,那为什么不直接用C或C++呢? 
  程序员有必要知道为什么做某个功能吗? 
  多核CPU中,利用多线程进行排序中出现了一些奇怪的现象,不知道其背后的原因是什么,希望有人能给予解答? 
  为什么 Windows 系统 Program Files 这个经常用来装软件的目录,名称中有个空格? 
  C/C++ 标准库为什么不支持直接删除一个文件中的部分内容? 
  Java 集合类库的顶层里的 Collection,List,Set 是抽象类的话是否更“正确”一些? 
  为什么有人坚信人类不可能基于 GUI 的操作方式,发明出比「命令式编辑器」效率更高的开发环境? 
  C#中的typeof()是一个函数吗? 
  C的结构体成员变量的命名有必要加前缀吗? 
  C语言 乘以0.01快?还是除以100快? 

前一个讨论
总会有人比你强,既然这样你是怎么做到保持自信的?
下一个讨论
UDP 和 TCP 的 socket 分别一般用在什么地方?





© 2024-12-22 - tinynew.org. All Rights Reserved.
© 2024-12-22 - tinynew.org. 保留所有权利