我的大脑会爆炸。 :)因此,我想从您那里获得帮助。
请考虑我的问题,就像只是程序员难题一样。 (实际上。也许对您来说这是一个非常简单的问题,但对我而言不是。)
需要创建对象数组。例如列表,其中T是类。 (我将在下面描述T类)。此外,还需要创建“容器”,其中将包含此数组以及与此数组一起使用的一些方法。例如Add(),Remove(int IndexToRemove)。
T类必须具有字段“ Container”,这样,数组的每个元素都将能够知道其包含在何处,并可以访问其容器的字段和方法。注意,在这种情况下,Class T应该具有类型参数。确实,事先不知道使用哪种容器类型。
让我们将此类容器表示为A,将类元素(类T)表示为AUnit。
码:
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a.Units[0].SomeField +=100;
Console.ReadKey();
}
}
class A
{
public List<AUnit> Units;
public A()//ctor
{
Units = new List<AUnit>();
}
public void Add()
{
this.Units.Add(new AUnit(this));
}
}
class AUnit
{
public int SomeField;
public A Container;
public string Name { get; private set; }
public AUnit(A container)
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
}
}
当然,公共字段应该受到保护或为私有,但稍后再考虑。
您可以问“为什么我们要在AUnit中创建公共的A容器字段”?我们创建字段公共字符串Name {get; private set;}(实际上是属性,但没关系)。而且我们还希望能够更改此字段的值,例如方法[Class AUnit] public bool Rename(string newName)();。此方法的主要思想是仅在数组(公共列表单元;)中没有一个元素具有与newName相同的名称的情况下更改Name字段。但是要实现这一点,重命名方法必须有权访问当前使用的所有名称。这就是为什么我们需要Container字段。
扩展版本AUnit的代码
class AUnit
{
public int SomeField;
public A Container;
public string Name { get; private set; }
public AUnit(A container)
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
}
public bool Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.Units)
{
if (unt.Name == newName)
{
res = false;
break;
}
}
if (res) this.Name = String.Copy(newName);
return res;
}
}
好。如果您仍然阅读它,让我们继续。现在我们需要创建B类和BUnit类,它们将与A类和Aunit类非常相似。最后,这个难题的主要问题是我们如何做到这一点?当然,我可以复制粘贴并修改A和AUnit并创建此代码。
class B
{
public List<BUnit> Units; //Only Type Changing
public B()//ctor Name changing...
{
Units = new List<BUnit>();//Only Type Changing
}
public void Add()
{
this.Units.Add(new BUnit(this));//Only Type Changing
}
}
class BUnit
{
public int SomeField;
public B Container;//Only Type Changing
public string Name { get; private set; }
public A a; //NEW FIELD IS ADDED (just one)
public BUnit(B container) //Ctor Name and arguments type changing
{
this.SomeField = 43;
this.Container = container;
this.Name = "Default";
this.a=new A(); //New ROW (just one)
}
public bool Rename(String newName)
{
Boolean res = true;
foreach (BUnit unt in this.Container.Units) //Only Type Changing
{
if (unt.Name == newName)
{
res = false;
break;
}
}
if (res) this.Name = String.Copy(newName);
return res;
}
}
我可以通过这种方式使用此类。
static void Main(string[] args)
{
B b = new B();
b.Add();
b.Units[0].a.Add();
b.Units[0].a.Units[0].SomeField += 100;
bool res= b.Units[0].a.Units[0].Rename("1");
res = b.Units[0].a.Units[0].Rename("1");
Console.ReadKey();
}
此构造可用于创建“非均匀树”。
帮忙,我需要别人的帮助,但没有人……。 [披头士]
我使用CopyPaste创建了B和BUnit。
但是,如何使用“宏定义”或“泛型”,继承或其他优雅的样式来完成呢? (C#语言)
我认为没有理由描述我所有的失败尝试和子问题。已经话题太长。 :)
非常感谢您仍然阅读并理解我的要求。
最佳答案
您需要实现一个基本类型,将其称为UnitBase
,具有所有常用功能。我将通过以下方式构建代码:
为您的容器创建一个接口,这样您就可以将实现更改为性能更高的解决方案,而无需修改要添加到容器中的元素。
public interface IContainer
{
Q Add<Q>() where Q : UnitBase, new();
IEnumerable<UnitBase> Units { get; }
}
按照1中所述的想法,为什么不使搜索逻辑属于容器?这更有意义,因为它主要取决于容器的实现方式:
public interface IContainer
{
Q Add<Q>() where Q : UnitBase, new();
IEnumerable<UnitBase> Units { get; }
bool Contains(string name);
}
IContainer
的特定实现可以如下:public class Container : IContainer
{
public Container()
{
list = new List<UnitBase>();
}
private List<UnitBase> list;
public Q Add<Q>() where Q: UnitBase, new()
{
var newItem = Activator.CreateInstance<Q>();
newItem.SetContainer(this);
list.Add(newItem);
return newItem;
}
public IEnumerable<UnitBase> Units => list.Select(i => i);
public bool Contains(string name) =>
Units.Any(unit => unit.Name == name);
}
为您的
AUnit
和BUnit
类型创建基类,以凝聚所有常用功能:public abstract class UnitBase
{
protected UnitBase()
{
}
public IContainer Container { get; private set; }
public int SomeField;
public string Name { get; private set; }
public void SetContainer(IContainer container)
{
Container = container;
}
public bool Rename(String newName)
{
if (Container.Contains(newName))
return false;
this.Name = newName; //No need to use String.Copy
return true;
}
}
实施您的具体类型:
public class BUnit : UnitBase
{
public int SpecificBProperty { get; private set; }
public BUnit()
{
}
}
这种方法的缺点?好吧,容器必须是
<UnitBase>
类型,我已经删除了泛型类型,因为在这种特殊情况下它实际上没有做很多事情,因为它在泛型类型中是不变的。另外,请记住,类型系统中的任何事物都不能避免以下情况:
myContainer.Add<BUnit>();
myContainer.Add<AUnit>();
如果在同一个容器中没有两种不同的类型,那么整个设置过程就会崩溃。以前的解决方案中也存在此问题,因此它不是新问题,我只是忘记指出了。