Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/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#_Design Patterns - Fatal编程技术网

C# C语言中的数据继承#

C# C语言中的数据继承#,c#,design-patterns,C#,Design Patterns,在分层对象结构中是否存在继承数据的已知模式?我有一个分层的“项”结构,需要从其“父项”继承其“类型”(与默认值具有相同的数据)。子项的类型可以自行修改,当父项的类型发生变化时,其类型未发生变化的所有子项都应获得新的父项类型 注意,我不能像这样假装它 public string Type { get { if (type == null) return Parent != null ? Parent.Type : null;

在分层对象结构中是否存在继承数据的已知模式?我有一个分层的“项”结构,需要从其“父项”继承其“类型”(与默认值具有相同的数据)。子项的类型可以自行修改,当父项的类型发生变化时,其类型未发生变化的所有子项都应获得新的父项类型

注意,我不能像这样假装它

public string Type
{
    get
    {
        if (type == null)
            return Parent != null ? Parent.Type : null;

        return type;
    }
}
'因为我必须填充数据库中的值,而且结构太深,无法使用递归,而且不担心性能

我现在唯一能想到的就是

public string Type
{
    set
    {
        type = value;
        UpdateUnchangedChildren(value);
    }
}

public int AddChild(Item item)
{
    item.Type = Type;
    return Items.Add(item);
}
有更好的办法吗?
谢谢。

我不是100%确定你想做什么。。。但是您可以使用泛型将父对象的类型传递给子对象。。。但是在那里有一个二传手真的没有意义。。。父对象的类型将在实例化时设置,所以为什么要在那里设置一个setter来更改它呢

假设你有这样的东西

public class Child<T>
{
   public string Type
   {
       get { return typeof(T).ToString(); }
   }
}
调用这些ChildObj.Type属性中的任何一个将分别返回ParentA、ParentB和ParentC

但我有一种奇怪的感觉,你还没有完全解释你想做什么。 您是否可以发布更多显示父类和子/项类的代码示例?“…结构太深,无法使用递归,因此不必担心性能。”

你真的量过这个吗?您要处理多少项,结构有多深,项没有自己的“类型”值有多常见?应用程序的性能目标是什么,递归解决方案与这些目标相比如何

人们通常认为递归很慢,因此在不尝试递归的情况下就将其排除在考虑之外。出于性能原因而拒绝最简单的设计,而不首先对其进行测量,这绝不是一个好主意。否则,你会去发明一个更复杂的解决方案,而更简单的解决方案会很好地工作


当然,您的第二个解决方案也使用递归,只是沿着层次结构向下而不是向上。如果子插入发生在不同的时间,并且可以吸收可能的性能影响,那么这可能更容易接受。

这是一个常见问题,通常与维护各种层次设置/配置有关。因此,我想解决这个问题的办法可以被视为“一种模式”

无论如何,从内部架构的角度来看,您有两个主要选择:

  • 规范化结构
  • 非规范化结构
“Normazlied”是用递归实现的。一个特定的数据块总是存储在一个地方,所有其他地方都有对它的引用(例如,父级)。结构很容易更新,但从中读取可能会有问题

“非规范化”意味着每个节点都将存储其级别的整个设置集,并且每当更新节点时,都需要花费一些时间来遍历层次结构并更正所有子节点。但是读取操作是即时的

因此,“非规范化”版本似乎得到了更广泛的应用,因为设置的常见情况是很少更新它们,而经常读取它们,因此需要更好的读取性能。例如,使用“非规范化”方法快速进行安全检查。你可以看看他们是怎么做的。但是,对于您的特定系统来说,这可能是一种过度的杀伤力,您可以简单地设置一个标志,表明某个特定值被覆盖,或者相反,重置为“默认值”


进一步的细节取决于您的系统需求,您可能需要一个“混合”架构,其中一些字段将被“规范化”,而另一些字段则不会。但是您似乎走对了路。

一个明显的优化是在读取类型时缓存从父级获得的值。这意味着您最多只遍历一次每个路径(而简单的解决方案意味着您将为包含它的每个路径一次又一次地遍历每个子路径,这意味着最多遍历O(h^2),而不是O(h))。如果你读的比写的多,那就太好了

考虑这一点:

class Node
{
    string _cachedParentType = null;
    string _type;
    string Type 
    {
        get { return _type ?? _cachedParentType ?? (_cachedParentType = Parent.Type); }
        set 
        { 
            _type = value; 
            foreach (var child in Children) { child._cachedParentType = null; }
        }
    }
}

这意味着,如果读的次数足够,写的次数很少,那么在最好的情况下,读变成O(1),或者在最坏的情况下,“缓存未命中”将花费O(h),h是树的高度;而更新是O(k),k是分支级别(因为我们只向下更新一层!)。我认为这通常会比UpdateOnChangedChildren解决方案(我假设它会递归地更新节点,一直更新到Leaf)好,除非您的读操作比写操作多得多

好的,我会试着解释更多。关于递归的观点很好,但是是的,我已经测试过了,我认为延迟加载和递归不是一对很好的组合。正如您所说的,加载值比更改值更频繁。它不需要递归地更新节点直到叶子吗?这样,如果孙子节点缓存了其父节点的类型(而父节点的类型又是祖父母的类型),并且祖父母的类型发生了更改,则孙子节点将返回无效值。
class Node
{
    string _cachedParentType = null;
    string _type;
    string Type 
    {
        get { return _type ?? _cachedParentType ?? (_cachedParentType = Parent.Type); }
        set 
        { 
            _type = value; 
            foreach (var child in Children) { child._cachedParentType = null; }
        }
    }
}