Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建只能由特定类使用的构造函数。(C+;+;在C#中相当于朋友) 据我所知,在C语言中,C++中没有“朋友”关键字的支持。有没有其他方法可以设计一个类来实现相同的最终结果,而不必使用不可用的“friend”关键字_C#_Constructor - Fatal编程技术网

如何创建只能由特定类使用的构造函数。(C+;+;在C#中相当于朋友) 据我所知,在C语言中,C++中没有“朋友”关键字的支持。有没有其他方法可以设计一个类来实现相同的最终结果,而不必使用不可用的“friend”关键字

如何创建只能由特定类使用的构造函数。(C+;+;在C#中相当于朋友) 据我所知,在C语言中,C++中没有“朋友”关键字的支持。有没有其他方法可以设计一个类来实现相同的最终结果,而不必使用不可用的“friend”关键字,c#,constructor,C#,Constructor,对于那些还不知道的人,Friend关键字允许程序员指定类“X”的成员只能被类“Y”访问和使用。但对于任何其他类,该成员都是私有的,因此无法访问。类“Y”不必从类“X”继承。不,在C#中没有这样做的方法 一种常见的解决方法是基于要在接口上隐藏其构造函数的对象。然后可以使用另一个对象构造实现该接口的私有嵌套类,并通过工厂返回该类。这会阻止外部世界直接构建对象,因为它们只会看到接口并与接口交互 public interface IMyObject { void DoSomething();

对于那些还不知道的人,Friend关键字允许程序员指定类“X”的成员只能被类“Y”访问和使用。但对于任何其他类,该成员都是私有的,因此无法访问。类“Y”不必从类“X”继承。

不,在C#中没有这样做的方法

一种常见的解决方法是基于要在接口上隐藏其构造函数的对象。然后可以使用另一个对象构造实现该接口的私有嵌套类,并通过工厂返回该类。这会阻止外部世界直接构建对象,因为它们只会看到接口并与接口交互

public interface IMyObject
{
     void DoSomething();
}

public class MyFriendClass
{
     IMyObject GetObject() { return new MyObject(); }

     class MyObject : IMyObject
     {
          public void DoSomething() { // ... Do something here
          }
     }
}

不。最接近的是
内部
构造函数,或
私有
构造函数和单独的工厂方法(可能是
内部
,因此您没有节省太多)。

据我所知,internal关键字是.NET中最接近的东西。这个问题将进一步说明内部问题:

让它明确地实现一个只对某个类可见的接口怎么样

比如:

public void IFreindOfX.Foo() //This is a method in the class that's a 'friend' to class X.
{
   /* Do Stuff */
}

然后确保IFriendOfX对类X可见。在X类中,首先将X强制转换为IFriendOfX,然后调用Foo()来调用该方法。另一个优点是,它是相当自我记录的。。。也就是说,它非常接近于拥有friend关键字本身。

作为一种解决方法,我想您可以在构造函数中创建一个使用反射的条件

例如,如果Class1的构造函数必须由Class2调用:

public Class1()
{
    string callingClass = new StackFrame(1).GetMethod().DeclaringType.Name;

    if (callingClass != "Class2")
    {
        throw new ApplicationException(
            string.Concat("Class1 constructor can not be called by ",
            callingClass, "."));
    }
}
编辑:


请注意,我永远不会在“真实”代码中实际执行此操作。从技术上讲,这是可行的,但它相当令人讨厌。我只是觉得这很有创意

您可以使用反射访问私有成员/方法


因为它有设计标签,我从来没有特别喜欢过friend关键字。它穿透了封装,我总觉得它很脏。

这有点味道。还有很多其他方法可以实现隐藏在C中的实现。仅将构造限制在特定的类并不能实现所有这些


你能提供更多关于这项要求目的的信息吗?如前所述,
internal
是限制类的可访问性的最匹配项。根据用途的不同,有多种方法可以在此基础上进行构建。

我所能想到的唯一接近的方法是
受保护的内部
,但这并不局限于特定的类。在c#中我所知道的唯一的友谊就是结交朋友。仍然不限于特定的类

我能想到的唯一一件事就是尝试并做如下事情:

public class A
{
   public A() {}
   protected internal A(B b) {}
}

public class B
{
   A myVersion;

   public B() 
   {
      myVersion = A(this);
   }
}

我唯一能想到的另一种方法是使用在friend类中完成的反射来执行某种构造函数注入。注入机制允许您将其限制在您想要的范围内,但可能非常麻烦。看看Spring.Net之类的注入功能。

创建一个私有类怎么样?这正是你所描述的。类
X
的成员只能由类
Y
访问和使用,对于任何其他类,它都是私有的,因为它是私有的:


我就是这样解决的。我不确定这是否是一种“正确”的方式,但它只需要很少的努力:

public abstract class X
{
    // "friend" member
    protected X()
    {
    }

    // a bunch of stuff that I didn't feel like shadowing in an interface
}

public class Y
{
    private X _x;

    public Y()
    {
        _x = new ConstructibleX();
    }

    public X GetX()
    {
        return _x;
    }

    private class ConstructibleX : X
    {
        public ConstructibleX()
            : base()
        {}
    }
}

另外,我想知道微软是否正在考虑将这样一个功能放到.Net 4.0中。不,他们没有。NET 4保留了与以前版本相同的可访问性修饰符。请记住,“protected internal”(受保护的内部)是指受保护的和内部的更宽松的组合,而不是不那么宽松的组合。我希望在不同的程序集中定义friend类。但是,有没有可能告诉私有类位于不同的命名空间中?这只适用于对象,对构造函数不起作用,但我真的不明白为什么需要这样做,除非你说的是,只有在某些状态下,当对象被朋友使用时才是有效的。在这种情况下,您真的希望从所讨论的类中派生出一个新的“友好”类,该类仅对“Friend”类可见。我必须在对象的位置和名称空间上妥协一点。。。但它确实实现了我想要做的,+1好吧,接口可以在不同的名称空间中,因此不应该有任何妥协。不幸的是,对象(在代码中)的位置确实发生了变化,遵循这种模式。如果希望嵌套类位于单独的文件中,可以将
MyFriendClass
声明为一个分部类。与@ReedCopsey相比,我更喜欢这种方法,因为这样我实际上可以定义类。接口不适合我,因为我还需要定义字段+1,非常简洁。使用抽象类很聪明!
public abstract class X
{
    // "friend" member
    protected X()
    {
    }

    // a bunch of stuff that I didn't feel like shadowing in an interface
}

public class Y
{
    private X _x;

    public Y()
    {
        _x = new ConstructibleX();
    }

    public X GetX()
    {
        return _x;
    }

    private class ConstructibleX : X
    {
        public ConstructibleX()
            : base()
        {}
    }
}