gpt4 book ai didi

共同 friend 类的 C# 解决方法

转载 作者:太空狗 更新时间:2023-10-30 00:47:47 29 4
gpt4 key购买 nike

所以,我有一个类似于 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; }
}

但是,我想实现所有以下行为:

  1. 在插入/删除节点时更新 Cycle.Count
  2. 允许“空”循环(即Origin = null)为Origin 创建一个新的Node >
  3. 防止在情况 1 和 2 之外构造新的 Node 对象
  4. 避免暴露不需要被这两个以外的类调用的方法

在 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com