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