gpt4 book ai didi

c# - 如何处理将父对象作为参数传递?

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

我不确定我所做的是完全无效还是仅仅是糟糕的练习,但我有一个类(class),我们称之为 Bar ,这是一些父类的字段,我们称之为Foo , 和 Bar 之一的方法要求我传递父实例 Foo作为论据。这似乎是一个糟糕而困惑的想法,但我想不出更好的方法来做到这一点。 Foo有效地存储了一些 List<Bar> , Bar , ConcurrentDictionary<string,Bar> ,或类似的,用于让我建立我所有的 Bar没有重复数据的实例。

代码的原理是这样的:

public class Foo
{
public List<Bar1> bar1List {get;set;}
public List<Bar2> bar2List {get;set;}
}

public abstract class Bar
{
//EDITED TO IMPROVE EXAMPLE
public int Value {get;set;}
public void DoSomething(Foo parentFoo)
{
}
}

public class Bar1 : Bar
{
public override void DoSomething(Foo parentFoo)
{
//EDITED TO GIVE AN EXAMPLE OF DoSomething()
this.Value = this.Value + parentFoo.bar2List[0].Value:
}
}

public class Bar2 : Bar
{
public override void DoSomething(Foo parentFoo)
{
//some other code
}
}

Foo foo = new Foo()
//populate foo somehow

foo.bar1List[0].DoSomething(foo);
//this is what looks very odd to me and feels kind of like a circular reference. The code will never be circular in that if I want to change bar1List within DoSomething() I will do it by "this", not foo.bar1List.

我考虑过制作每个 List<BarX> (其中 X 是一个数字)BarX 的静态字段但这不起作用,因为一切都是多线程的,我想要 List<BarX> 的多个实例;我考虑过使用标准方法访问父对象,但我不明白如果我有两个 parent 一个人,这不会变得困惑 List<BarX> .有什么想法/提示吗?我不想移动 DoSomething方法出Bar .

编辑实际问题的描述:如前所述,Foo用作所有各种 Bar 的存储库实例;所有 Bar实例交织在一起 Bar1可能包含 List<Bar> .一家Bar s,例如 List<Bar1>规定为程序输入;其余的 BarX然后根据需要使用配置文件和逻辑的全部负载从该列表创建列表等。 Bar一共有9种口味,以非线性方式排列,例如我的第一个Bar1实例可能需要 Bar7实例,这又需要另一个 Bar1实例(在初始 List<Bar1> 中不存在)等等。每个BarX味道有Generate()代替DoSomething()的方法以确定如何构建它。这种安排非常适合线程,因此需要一个并发位置来保存所有这些实例,其中基本思想是 IfExists,返回它并分配给字段/列表/其他;否则构建它并将其添加到 ConcurrentDictionary .

最佳答案

你可以实现这样的事情的方法之一是为你的 Foo 类实现一个 ObservableCollection 来监听列表中的变化,并在添加/删除时项,您可以将父项添加到子栏项。

像这样,您的方法不必引用父级,但它可以通过类型为 Foo 的属性 Parent 访问它。

因为它们都将在 Foo 实例中引用相同的 Foo 实例,所以您不会有重复的数据。

作为此类实现的示例,您可以这样做

首先定义一个接口(interface),提供对 Parent 属性的轻松访问

public interface IChild<T>
{
T Parent { get; }
}

我们可以对 Bar 的 DoSomething 方法做同样的事情

public interface IBar
{
void DoSomething();
}

然后在 Bar 的抽象版本中实现这两个接口(interface),留下 DoSomething 方法抽象

public abstract class Bar : IChild<Foo>, IBar
{
private Foo parent;
public Foo Parent
{
get
{
return parent;
}
set
{
parent = value;
}
}

public abstract void DoSomething();
}

并实现 Bar 的 2 个版本,例如:

public class Bar1 : Bar
{
public override void DoSomething()
{
if (this.Parent == null)
{
throw new ArgumentException("Parent cannot be null");
}
// code against parent
Console.WriteLine("Bar 1 doing something");
}
}

public class Bar2 : Bar
{
public override void DoSomething()
{
if (this.Parent == null)
{
throw new ArgumentException("Parent cannot be null");
}
// code against parent
Console.WriteLine("Bar 2 doing something");
}
}

然后,您仍然需要对您的 Foo 类进行一些更改,该类将自身注册到集合 (Bar1Collection, Bar2Collection) 并提供一种方法来监听集合中的变化。它还实现了 IDisposable 接口(interface),以便我们可以在不再需要 Foo 类时从 CollectionChanged 事件中注销

public class Foo : IDisposable
{
private readonly IList<Bar> bar1Collection = new ObservableCollection<Bar>();
public IList<Bar> Bar1Collection
{
get
{
return bar1Collection;
}
}

private readonly IList<Bar> bar2Collection = new ObservableCollection<Bar>();
public IList<Bar> Bar2Collection
{
get
{
return bar2Collection;
}
}

protected void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{
foreach (var item in e.OldItems)
{
if (item is Bar)
{
var bar = item as Bar;
bar.Parent = null;
}
}
}
if (e.NewItems != null)
{
foreach (var item in e.NewItems)
{
if (item is Bar)
{
var bar = item as Bar;
bar.Parent = this;
}
}
}
}

protected void RegisterCollection(INotifyCollectionChanged collection)
{
if (collection == null)
{
return;
}
collection.CollectionChanged += OnCollectionChanged;
}

protected void UnregisterCollection(INotifyCollectionChanged collection)
{
if (collection == null)
{
return;
}
collection.CollectionChanged -= OnCollectionChanged;
}

public Foo()
{
RegisterCollection(Bar1Collection as INotifyCollectionChanged);
RegisterCollection(Bar2Collection as INotifyCollectionChanged);
}

private bool isDisposed = false;
protected virtual void Dispose(bool disposing)
{
if (!disposing || isDisposed)
{
return;
}
isDisposed = true;
UnregisterCollection(Bar1Collection as INotifyCollectionChanged);
UnregisterCollection(Bar2Collection as INotifyCollectionChanged);
}

public void Dispose()
{
Dispose(true);
}
}

作为测试方法,此控制台程序随后可以针对它运行

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;

namespace BarFoo
{
class Program
{
static void Main(string[] args)
{
Foo foo1 = new Foo();
Bar bar1 = new Bar1();
Bar bar2 = new Bar2();
foo1.Bar1Collection.Add(bar1);
foo1.Bar2Collection.Add(bar2);
Debug.Assert(bar1.Parent != null);
Debug.Assert(bar2.Parent != null);
bar1.DoSomething();
bar2.DoSomething();
Console.WriteLine("Done");
Console.ReadLine();
foo1.Dispose();
}
}
}

关于c# - 如何处理将父对象作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30173498/

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