C# 在c中如何按所有者控制类可见性#

C# 在c中如何按所有者控制类可见性#,c#,class,visibility,C#,Class,Visibility,通常我希望某些类C1的某些(或全部)函数只能从另一个类C2中访问,因为C2是一种代理,它拥有C1类型的对象(例如,类“Neuron”的方法,如“connect()”,应该只能从“Brain”访问)。我假设这在C#中不可能直接实现,这与继承不同,继承可以使用关键字“private”或“protected”指定可见性 在这种情况下,最好的做法是什么?如果C1只能被C2访问,那么将C1设为C2的私有类 public class C2 { public C2() { } private

通常我希望某些类C1的某些(或全部)函数只能从另一个类C2中访问,因为C2是一种代理,它拥有C1类型的对象(例如,类“Neuron”的方法,如“connect()”,应该只能从“Brain”访问)。我假设这在C#中不可能直接实现,这与继承不同,继承可以使用关键字“private”或“protected”指定可见性


在这种情况下,最好的做法是什么?

如果
C1
只能被
C2
访问,那么将
C1
设为
C2
的私有

public class C2
{
    public C2() { }

    private class C1
    {
        public C1() { }
    }
}
但是,如果可以在
C2
之外访问
C1
,则需要将某种
传入
C2
ctor
,以确保它是一个可信的代理

public class C1
{
    public C1(string key)
    {
        // verify that it's a valid proxy or user of this class via the key
    }
}

为类创建程序集,并将外部世界看不到的内部类声明为
internal

:

internal
关键字是类型和类型成员的访问修饰符。内部类型或成员只能在同一程序集中的文件中访问

比如说:

namespace YourAssembly.Classes
{
    internal class C1
    {
        public void Foo()
        {
        
        }
    }
    
    public class C2
    {
        public void DoFoo()
        {
            new C1().Foo();     
        }
    }
}
public interface INeuron 
{
   double GetValue();
   List<INeuron> GetDependents();
   List<double> GetWeights();
}

internal class Neuron : INeuron
{
   // implementation of INeuron
   // ...

   // implementation of methods only known to own classes
   public void Connect(Neuron target, double weight)
   {
      ...
   }
}

public class Brain
{
   private List<Neuron> _allNeurons = new List<Neuron>();       

   public Brain()
   {
      Neuron n1 = new Neuron();
      Neuron n2 = new Neuron();
      n1.Connect(n2,0.5);
      _allNeurons.Add(n1);
      _allNeurons.Add(n2);
   }

   public IEnumerable<INeuron> GetAllNeurons() { return _allNeurons.Cast<INeuron>(); }
}

此处
C2
可从其他组件访问,而
C1
只能从同一组件内访问。

通常用于测试目的的技巧是使用。您可以像这样将其应用于程序集(exe或dll)

[assembly: InternalsVisibleTo("NameOfFriendAssembly")]

类(和其他类型)和定义为
内部
的成员将在内部可见,但也对程序集可见
NameOfriendaAssembly
在我看来,对您来说最好的方法是这样做:

namespace YourAssembly.Classes
{
    internal class C1
    {
        public void Foo()
        {
        
        }
    }
    
    public class C2
    {
        public void DoFoo()
        {
            new C1().Foo();     
        }
    }
}
public interface INeuron 
{
   double GetValue();
   List<INeuron> GetDependents();
   List<double> GetWeights();
}

internal class Neuron : INeuron
{
   // implementation of INeuron
   // ...

   // implementation of methods only known to own classes
   public void Connect(Neuron target, double weight)
   {
      ...
   }
}

public class Brain
{
   private List<Neuron> _allNeurons = new List<Neuron>();       

   public Brain()
   {
      Neuron n1 = new Neuron();
      Neuron n2 = new Neuron();
      n1.Connect(n2,0.5);
      _allNeurons.Add(n1);
      _allNeurons.Add(n2);
   }

   public IEnumerable<INeuron> GetAllNeurons() { return _allNeurons.Cast<INeuron>(); }
}
欧元区的公共界面 { 双GetValue(); 列出GetDependents(); 列出GetWeights(); } 内类神经元:伊内隆 { //INeuron的实施 // ... //只有自己的类知道的方法的实现 公共连接(神经元目标,双重重量) { ... } } 公共阶层的头脑 { 私有列表_allNeurons=新列表(); 公共大脑() { 神经元n1=新神经元(); 神经元n2=新神经元(); n1.连接(n2,0.5); _所有神经元。添加(n1); _所有神经元。添加(n2); } public IEnumerable GetAllNeurons(){return allNeurons.Cast();} }
是的,我忘了提到私有类不是选项,因为C2的函数必须可以被其他几个类访问。此解决方案通过添加运行时执行来解决编译时问题。这不是正确的方法。@MichaelPerrenoud:问题是编译时的问题。这里的目的是防止其他程序员访问他们不应该访问的方法。您的解决方案意味着在运行时使用逻辑,即每次调用方法时都要确定一个键是正确的。此解决方案会损害代码的性能…
internal
对整个DLL可见,而不是对命名空间可见。如果不小心,您仍然可以从程序集中的任何其他类调用Connect()。真正需要的是编译器对这个问题的支持。@Yekoor:我不同意。你看,我认为你犯了一个非常常见的错误,那就是从类的概念而不是API访问的角度来考虑代码的可见性。
Neuron
上的方法是公开的,因为应该允许DLL的外部客户端访问它,而不是因为
Brain
应该能够连接
Neuron
s。在您自己的库中,您有责任不调用不应该调用的方法。代码可见性应仅用于控制依赖于DLL且由internal关键字控制的项目。您编写的内容与问题的定义不兼容。我没有一个库,即使我没有显式地声明它,所以我不考虑API访问。如果理论上我们可以像继承访问控制一样将其委托给编译器,那为什么这是我自己的责任呢?我要说的是,方法可见性不应该用于建模问题,而应该用于限制DLL可用的内容(主要是限制依赖项)。这与
大脑
是否应该能够访问
Neuron.Connect()
无关