首页 文章

什么是C#相当于朋友? [重复]

提问于
浏览
168

可能重复:为什么C#不提供C风格的'friend'关键字?

我希望类的私有成员变量可以被Tester类访问,而不会将它们暴露给其他类 .

在C中,我只是将Tester类声明为朋友,如何在C#中执行此操作?有人能举个例子吗?

5 回答

  • 238

    有's no direct equivalent of 1812860 - the closest that'可用(并且它不是非常接近)是InternalsVisibleTo . 我've only ever used this attribute for testing - where it'非常方便!

    Example: 待于 AssemblyInfo.cs

    [assembly: InternalsVisibleTo("OtherAssembly")]
    
  • 6

    壁橱等效于创建一个嵌套类,它将能够访问外部类的私有成员 . 像这样的东西:

    class Outer
    {
        class Inner
        {
           // This class can access Outer's private members
        }
    }
    

    或者如果您更喜欢将Inner类放在另一个文件中:

    Outer.cs
    partial class Outer
    {
    }
    
    
    Inner.cs
    partial class Outer
    {
        class Inner
        {
           // This class can access Outer's private members
        }
    }
    
  • 13

    采取一种非常常见的模式 . Class Factory制作小部件 . 工厂类需要与内部进行混淆,因为它是工厂 . 两者都在同一个文件中实现,并且根据设计和愿望与性质,紧密耦合的类 - 事实上,Widget实际上只是工厂的输出类型 .

    在C中,使Factory成为Widget类的朋友 .

    在C#中,我们能做什么?我遇到的唯一合适的解决方案是创建一个接口IWidget,它只公开公共方法,并让Factory返回IWidget接口 .

    这涉及相当多的单调乏味 - 在界面中再次暴露所有自然公共 property .

  • 67

    C#中没有'friend'关键字,但测试私有方法的一个选项是使用System.Reflection来获取方法的句柄 . 这将允许您调用私有方法 .

    给定一个具有此定义的类:

    public class Class1
    {
        private int CallMe()
        {
            return 1;
        }
    }
    

    您可以使用以下代码调用它:

    Class1 c = new Class1();
    Type class1Type = c.GetType();
    MethodInfo callMeMethod = class1Type.GetMethod("CallMe", BindingFlags.Instance | BindingFlags.NonPublic);
    
    int result = (int)callMeMethod.Invoke(c, null);
    
    Console.WriteLine(result);
    

    如果您正在使用Visual Studio Team System,那么您可以通过右键单击该方法并选择“Create Unit Tests ...”来让VS自动生成包含私有访问器的代理类 .

  • 40

    如果有权访问的类位于另一个包中,并且您公开的方法被标记为内部或内部受保护,则可以模拟朋友访问 . 您必须修改要共享的程序集,并将以下设置添加到AssemblyInfo.cs:

    // Expose the internal members to the types in the My.Tester assembly
    [assembly: InternalsVisibleTo("My.Tester, PublicKey=" +
    "012700000480000094000000060200000024000052534131000400000100010091ab9" +
    "ba23e07d4fb7404041ec4d81193cfa9d661e0e24bd2c03182e0e7fc75b265a092a3f8" +
    "52c672895e55b95611684ea090e787497b0d11b902b1eccd9bc9ea3c9a56740ecda8e" +
    "961c93c3960136eefcdf106955a4eb8fff2a97f66049cd0228854b24709c0c945b499" +
    "413d29a2801a39d4c4c30bab653ebc8bf604f5840c88")]
    

    公钥是可选的,具体取决于您的需求 .

相关问题