- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
所以,我有一个类似于 this one 的用例,但我觉得有一些额外的细节值得提出一个新问题。 ( related questions ,供引用)
我正在编写一个实现 a cycle 的数据结构.基本设计是这样的:
public class Cycle<T>
{
public Node<T> Origin { get; private set; }
public int Count { get; private set; }
}
public class Node<T>
{
public Cycle<T> Cycle { get; private set; }
public Node<T> Next { get; private set; }
public Node<T> Previous { get; private set; }
public T Value { get; set; }
}
但是,我想实现所有以下行为:
循环
(即Origin = null
)为Origin
创建一个新的Node
>Node
对象在 C++ 中,我只是让每个类成为另一个类的 friend
。但是在 C# 中,我看不到让它工作的方法。
我知道如果我将 Node
嵌套在 Cycle
中并且只为 Node
公开一个构造函数,我知道我可以完成除 #3 之外的所有内容,像这样:
public class Cycle<T>
{
public Node Origin { get; private set; }
public int Count { get; private set; }
public class Node
{
public Cycle<T> Cycle { get; private set; }
public Node Next { get; private set; }
public Node Previous { get; private set; }
public T Value { get; set; }
internal Node<T>(Cycle<T> cycle)
{
if (cycle.Origin != null)
throw new InvalidOperationException();
else
{
Cycle = cycle;
Next = this;
Previous = this;
cycle.Origin = this;
cycle.Count = 1;
}
}
}
}
但是如您所见,我只能达到内部
,所以我仍然必须验证数据完整性或破坏封装。
我确实有一个“聪明”的想法,但它是一种黑魔法答案:
public abstract class Cycle<T>
{
public Node Origin { get; private set; }
public int Count { get; private set; }
public sealed class Node
{
private CycleInternal _cycle;
public Cycle<T> Cycle { get { return _cycle; } }
public Node Next { get; private set; }
public Node Previous { get; private set; }
public T Value { get; set; }
// this constructor can be called by CycleInternal, but not other classes!
private Node(CycleInternal cycle)
{
Cycle = cycle;
Next = this;
Previous = this;
cycle.Origin = this;
cycle.Count = 1;
}
private sealed class CycleInternal : Cycle<T>
{
// this constructor can be called by Node, but not other classes!
public CycleInternal() {}
}
}
}
在这种情况下,我担心的是其他东西可能会继承自 Cycle;可以通过将 Cycle 的构造函数设为私有(private)来防止这种情况发生吗?或者我只是在这里偏执?
最佳答案
internal
exposes it to other classes in the same assembly, which I don't want to do
我的建议是:克服这种恐惧并将其标记为内部
。
我听过这个功能请求——C# 实现 C++ 风格的友元语义——很多很多次了。该功能的动机通常是担心“如果我允许程序集中的任何类对内部状态进行聚会,我的同事将滥用特权”。
但是您的同事已经有能力滥用该特权,因为您的同事已经可以添加 friend (在 C++ 中)或制作后门的内部方法(在C#)。
C# 辅助功能系统的设计根本不是为了保护您免受具有源代码写入权限的人对您的利益怀有敌意的情况的影响。正如 private
的意思是“这是这个类的一个实现细节”,protected
的意思是“这是这个层次结构的一个实现细节,internal
的意思是“这是该程序集的一个实现细节”。如果不能相信负责该程序集正确运行的同事会明智地使用他们的权力,请找更好的同事。如果您的类型需要访问彼此的内部细节以进行程序集作为一个整体可以正常工作,这就是 internal
的用途,所以请使用它。
或者,换句话说,这是一个社会问题,而不是技术问题,所以你应该通过施加社会压力来解决它。 C# 辅助功能系统并非旨在解决应由代码审查解决的问题。如果您的同事滥用他们的特权,代码审查时间就是让他们停止的时候,就像您使用代码审查来阻止他们向您的项目添加任何其他错误代码一样。
回答您的具体问题:
my worry is that something else could inherit from Cycle; could that be prevented by making the constructor to Cycle private?
是的,一个抽象类可以有一个私有(private)的构造函数,然后唯一的派生类型是嵌套类型。
我经常使用该模式,并将嵌套类型设为私有(private)。在 C# 中创建公共(public)的嵌套类型是一种难闻的气味。
旁白:通常我这样做是为了制作“案例类”,例如:
abstract class ImmutableStack<T>
{
private ImmutableStack() { }
private sealed class EmptyStack : ImmutableStack<T> { ... }
private sealed class NormalStack : ImmutableStack<T> { ... }
等等。这是一种很好的方式,可以将一个类型的实现细节分散到多个类中,但仍然全部封装到一个类中。
am I just being paranoid here?
我觉得是的。
关于共同 friend 类的 C# 解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55385718/
所以,我有一个类似于 this one 的用例,但我觉得有一些额外的细节值得提出一个新问题。 ( related questions ,供引用) 我正在编写一个实现 a cycle 的数据结构.基本设
我正在使用 Django 编写一个社交网络应用程序,需要实现类似于 Facebook“Mutual Friends”概念的功能。我有一个像这样的简单模型: class Friend(models.Mo
我有一个 iOS 应用程序,用户可以在其中使用 Facebook 登录并授予 user_friends 权限。从 Graph API 2.0 开始,Facebook 声称你无法获取两个人之间所有的共同
我想知道将来对我来说最简单的方法是什么,可以使查询既有效又不那么复杂。 我应该像这样保存双向关系吗 from_id=1, to_id=2from_id=2, to_id=1 或者只创建一个唯一的行 f
我是一名优秀的程序员,十分优秀!