我的大脑要爆炸了。)所以我想得到你的帮助。请考虑一下我的问题,就像关于程序员的难题一样。(实际上。也许这对你来说是个很简单的问题,但对我来说却不是。
需要创建对象数组。例如,列出T是类的列表。(我将在下面描述T类)。此外,还需要创建包含此数组的“容器”,以及用于处理该数组的一些方法。例如,Add(),Remove(int IndexToRemove)。类T必须有字段"Container",这样我们的数组中的每个元素都能够知道它包含在哪里,并且能够访问它的容器的字段和方法。注意,在这种情况下,类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中创建公共容器字段”?我们创建字段公共字符串名{get;私有集;}(实际上是属性,但没关系)。此外,我们还希望能够更改该字段的值,例如,方法类AUnit公共bool重命名(String newName)();。该方法的主要思想是只在数组中没有一个元素(公共列表单元;)具有与newName相同的名称时才更改Name字段。但是要实现这一点,重命名方法必须能够访问当前使用的所有名称。这就是为什么我们需要容器字段。
扩展版本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和类A单元。最后,这个难题的主要问题是我们如何才能做到这一点?当然,我可以CopyPaste和位修改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();
}这种结构可以用来创建“非同质树”。
救命,我需要有人帮忙,只是没有人…。甲壳虫乐队
我使用BUnit创建了B和CopyPaste。但是如何使用“宏定义”或“泛型”、继承或其他优雅风格的东西来完成呢?(C#语言)我认为没有理由描述我所有失败的尝试和子问题。话题已经太长了。:)
如果你还在读,明白我想问什么,那就谢谢你了。
发布于 2016-10-02 12:11:38
您需要实现一个基本类型,让我们称它为UnitBase,具有所有公共功能。我会按照以下方式构造您的代码:
IContainer的具体实现可以是:
公共类容器: IContainer { public容器(){ List =新列表();}私有列表列表;公共Q Add(),其中Q: UnitBase,新(){ var newItem = Activator.CreateInstance();newItem.SetContainer(this);list.Add(newItem);返回newItem;}公共单元=> list.Select(i => i);公共bool包含(字符串名称) => Units.Any(单元=> unit.Name ==名称);}AUnit和BUnit类型创建一个基类,凝聚所有公共功能:
公共抽象类UnitBase {受保护的UnitBase() }公共IContainer容器{ get;私有集;} public int SomeField;公共字符串名称{ get;私有集;}公共空SetContainer(IContainer容器){容器=容器;} public bool重命名( string newName) { if (Container.Contains(newName))返回false;this.Name = newName;//不需要使用String.Copy返回true;}这种方法的缺点?嗯,容器必须是<UnitBase>类型,我已经删除了泛型类型,因为在这种特殊情况下,它并没有做太多事情,因为它在泛型类型中是不变的。
此外,请记住,类型系统中没有任何东西可以避免以下情况:
myContainer.Add<BUnit>();
myContainer.Add<AUnit>();如果在同一个容器中有两个不同的类型不是一个选项,那么整个设置就会崩溃。这个问题在以前的解决方案中也存在,所以这不是什么新问题,我只是忘了指出它。
发布于 2016-10-03 14:17:59
InBetween,我非常感谢你的建议。事实上,我不能说我完全理解你的答案,但是我用你的想法做了我想做的事情。
看来我的变体很好用。不过,我想听听您(和每个人)对下面描述的代码的看法。这种结构的主要目标是创建非同质树。你能从这边估计一下吗。
首先。我们需要为两个类创建接口。我们描述了所有的“交叉使用”功能。
public interface IUnit<T>
{
string Name { get;}
void SetContainer(T t);
bool Rename(String newName);
}
public interface IContainer
{
bool IsNameBusy(String newName);
int Count { get; }
}下一首。为将来的继承创建单元类的基。我们将在这个容器库的继承者方法中使用,因此我们需要通用属性和IUnit接口。
class UnitBase<T> : IUnit<T> where T : IContainer不幸的是,我还不知道如何解决构造器参数的问题。所以我才用方法
SetContainer(T container).代码:UnitBase
class UnitBase<T> : IUnit<T> where T : IContainer
{
protected T Container;
public string Name { get; private set; }
public UnitBase()
{
this.Name = "Default";
}
public void SetContainer(T container)
{
this.Container = container;
}
public bool Rename(String newName)
{
bool res = Container.IsNameBusy(newName);
if (!res) this.Name = String.Copy(newName);
return !res;
}
}下一首。创建ContainerBase
ContainerBase应:
( 1)具有IContainer接口。
2)了解其中将包含哪些内容:
... where U : IUnit<C>, new() 3)和.有关于它本身的信息。我们需要将这些信息作为参数传递给SetContainer()方法。
代码ContainerBase:
class ContainerBase<U, C> : IContainer //U - Unit Class. C-Container Class
where U : IUnit<C>, new()
where C : ContainerBase<U, C>
{
protected List<U> Units;
public U this[int index] { get { return Units[index]; } }
public ContainerBase()//ctor
{
this.Units = new List<U>();
}
public void Add()
{
this.Units.Add(new U());
this.Units.Last().SetContainer(((C)this));//may be a bit strange but actualy this will have the same type as <C>
}
public bool IsNameBusy(String newName)
{
bool res = false;
foreach (var unt in this.Units)
{
if (unt.Name == newName)
{
res = true;
break;
}
}
return res;
}
public int Count { get { return this.Units.Count; } }
}Cast ((TContainer)(这个))可能有点奇怪。但是使用ContainerBase时,我们应该始终使用NewInheritorContainer。所以这个演员就是什么都不做…看上去..。
终于来了。这个类可以像在这个例子中一样使用。
class SheetContainer : ContainerBase<SheetUnit,SheetContainer> {public SheetContainer(){}}
class SheetUnit : UnitBase<SheetContainer>
{
public CellContainer Cells;
public PictureContainer Pictures;
public SheetUnit()
{
this.Cells = new CellContainer();
this.Pictures = new PictureContainer();
}
}
class CellContainer : ContainerBase<CellUnit, CellContainer> { public CellContainer() { } }
class CellUnit : UnitBase<CellContainer>
{
public string ValuePr;//Private Field
private const string ValuePrDefault = "Default";
public string Value//Property for Value
{
//All below are Just For Example.
get
{
return this.ValuePr;
}
set
{
if (String.IsNullOrEmpty(value))
{
this.ValuePr = ValuePrDefault;
}
else
{
this.ValuePr = String.Copy(value);
}
}
}
public CellUnit()
{
this.ValuePr = ValuePrDefault;
}
}
class PictureContainer : ContainerBase<PictureUnit, PictureContainer> { public PictureContainer() { } }
class PictureUnit : UnitBase<PictureContainer>
{
public int[,] Pixels{get;private set;}
public PictureUnit()
{
this.Pixels=new int[,]{{10,20,30},{11,12,13}};
}
public int GetSizeX()
{
return this.Pixels.GetLength(1);
}
public int GetSizeY()
{
return this.Pixels.GetLength(0);
}
public bool LoadFromFile(string path)
{
return false;
}
}
static void Main(string[] args)
{
SheetContainer Sheets = new SheetContainer();
Sheets.Add();
Sheets.Add();
Sheets.Add();
Sheets[0].Pictures.Add();
Sheets[1].Cells.Add();
Sheets[2].Pictures.Add();
Sheets[2].Cells.Add();
Sheets[2].Cells[0].Value = "FirstTest";
bool res= Sheets[0].Rename("First");//res=true
res=Sheets[2].Rename("First");//res =false
int res2 = Sheets.Count;
res2 = Sheets[2].Pictures[0].Pixels[1, 2];//13
res2 = Sheets[2].Pictures.Count;//1
res2 = Sheets[1].Pictures.Count;//0
res2 = Sheets[0].Pictures[0].GetSizeX();//3
Console.ReadKey();
}看上去像是我想要的。但我没有把它装满。让我再次感谢你,InBetween。
https://stackoverflow.com/questions/39816772
复制相似问题