- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我是 C# 的新手,我有一个问题,在 C++ 中我通常会使用 friend
标识符。现在我知道 C# 中不存在 friend
关键字,但我没有任何解决此问题的经验(除了使所有类变量成为公共(public)属性,如果我可以)。
我有以下场景:
public class A
{
public string Info { get; set; }
/* much more data */
}
public class B
{
private A m_instanceOfA;
public B(A a) { m_instanceOfA = a; }
public Info { get return A.info; set A.Info = value; }
/* And some more data of its own*/
}
public class C
{
private A m_instanceOfA;
// I need a constructor of C, which needs to set C.m_instanceOfA
// to the same value as b.m_instanceOfA.
public C(B b) { m_instanceOfA = b.m_instanceOfA ; } // <--- Not allowed!
/* And some more data of its own*/
}
有没有其他巧妙的方法,无需公开 B.m_instanceOfA
,就可以让 C
访问此变量(仅在构造函数中)?
最佳答案
您可以使用下面显示的技巧来创建一个方法 FriendRecieveMessageFromAlice
在 Bob 上只能由 Alice
调用.一个邪恶的类(class),Eve
,如果不对私有(private)成员使用反射,将无法调用该方法。
我很想知道其他人之前是否提出过这种或另一种解决方案。几个月来我一直在寻找解决该问题的方法,但我从未见过能确保真实的 friend
语义,前提是不使用反射(你几乎可以用它来规避任何事情)。
public interface IKey { }
public class Alice
{
// Alice, Bob and Carol must only have private constructors, so only nested classes can subclass them.
private Alice() { }
public static Alice Create() { return new Alice(); }
private class AlicePrivateKey : Alice, IKey { }
public void PublicSendMessageToBob() {
Bob.Create().FriendRecieveMessageFromAlice<AlicePrivateKey>(42);
}
public void FriendRecieveMessageFromBob<TKey>(int message) where TKey : Bob, IKey {
System.Console.WriteLine("Alice: I recieved message {0} from my friend Bob.", message);
}
}
public class Bob
{
private Bob() { }
public static Bob Create() { return new Bob(); }
private class BobPrivateKey : Bob, IKey { }
public void PublicSendMessageToAlice() {
Alice.Create().FriendRecieveMessageFromBob<BobPrivateKey>(1337);
}
public void FriendRecieveMessageFromAlice<TKey>(int message) where TKey : Alice, IKey {
System.Console.WriteLine("Bob: I recieved message {0} from my friend Alice.", message);
}
}
class Program
{
static void Main(string[] args) {
Alice.Create().PublicSendMessageToBob();
Bob.Create().PublicSendMessageToAlice();
}
}
public class Eve
{
// Eve can't write that, it won't compile:
// 'Alice.Alice()' is inaccessible due to its protection level
private class EvePrivateKey : Alice, IKey { }
public void PublicSendMesssageToBob() {
// Eve can't write that either:
// 'Alice.AlicePrivateKey' is inaccessible due to its protection level
Bob.Create().FriendRecieveMessageFromAlice<Alice.AlicePrivateKey>(42);
}
}
诀窍在于方法Bob.FriendRecieveMessageFromAlice
需要一个(虚拟的)泛型类型参数作为标记。该通用类型必须继承自 Alice
, 以及来自虚拟界面 IKey
.
自 Alice
不执行 IKey
本身,调用者需要提供一些子类 Alice
确实实现了IKey
.然而,Alice
只有私有(private)构造函数,因此它只能被嵌套类子类化,而不能被其他地方声明的类子类化。
这意味着只有一个类嵌套在Alice
中可以将其子类化以实现 IKey
.这就是AlicePrivateKey
确实如此,并且由于它被声明为私有(private),所以只有 Alice
可以将其作为通用参数传递给 Bob.FriendRecieveMessageFromAlice
, 所以只有 Alice
可以调用该方法。
然后我们反过来做同样的事情,这样只有Bob
可以调用Alice.FriendRecieveMessageFromBob
.
值得注意的是,调用时,Bob.FriendRecieveMessageFromAlice
可以访问 TKey
通用类型参数,并且可以使用它来欺骗来自 Alice
的调用在另一种方法上 OtherClass.OtherMethod<OtherTkey>
接受OtherTKey : Alice, IKey
.因此,让 key 从不同的接口(interface)继承会更安全:Alice, IBobKey
首先,Alice, IOtherKey
第二个。
Bob
本身不能调用自己的方法Bob.FriendRecieveMessageFromAlice
.Bob 可以拥有多个具有不同好友方法的好友:
// Can only be called by Alice, not by Carol or Bob itself
Bob.FriendRecieveMessageFromAlice <TKey>(int message) where TKey : Alice, IKey { }
// Can only be called by Carol, not by Alice or Bob itself
Bob.FriendRecieveMessageFromCarol <TKey>(int message) where TKey : Carol, IKey { }
我很想知道是否有某种方法可以比暴力试验和错误更有效地找到这样的技巧。某种“C# 类型系统的代数”,告诉我们可以强制执行哪些限制,哪些不能强制执行,但我还没有看到任何关于此类主题的讨论。
关于C# 等同于 C++ friend 关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19135534/
判断这2个相似的Uris实际上相同的标准方法是什么? var a = new Uri("http://sample.com/sample/"); var b = new Uri("http://sam
这个问题在这里已经有了答案: Why does "true" == true show false in JavaScript? (5 个答案) 关闭 5 年前。 可能我很困惑,但我无法理解这个愚蠢
我是一名优秀的程序员,十分优秀!