我正在为开发人员开发一个库,他们必须在其中创建一个继承自我创建的类的类。
此基类实质上是为开发人员管理对象的数组,但是开发人员可以指定他们希望基类管理的这些对象的类型。
因此,开发人员实质上只是告诉基类创建一个数组,然后仅对该数组具有只读访问权限。基类将(取决于应用程序的状态)在数组中添加或删除对象。
我一直坚持寻找合适的数据类型来存储这样的东西。我已经尝试过paintComponent(...)
和ref
,但那无济于事。我最接近的是out
,但是这个想法失败了,因为C#实际上只是将值复制到字典中,而不是引用或指向它。
这是我一起提出的一个简单例子:
Dictionary
输出:
public static void Main()
{
Derived d = new Derived();
d.InitBase();
d.Init();
d.CheckArray();
d.AddElement<GenericObject>(new GenericObject{ i = 2 });
d.CheckArray();
}
public class Base {
Dictionary<Type, List<object>> ArrayReferences;
public void InitBase() {
ArrayReferences = new Dictionary<Type, List<object>>();
}
protected ReadOnlyCollection<T> RegisterArray<T>() {
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
}
public void AddElement<T>(T obj) {
ArrayReferences[typeof(T)].Add(obj);
}
public void RemoveElement<T>(T obj) {
ArrayReferences[typeof(T)].Remove(obj);
}
}
public class Derived: Base {
ReadOnlyCollection<GenericObject> arr;
public void Init() {
arr = RegisterArray<GenericObject>();
}
public void CheckArray() {
Console.WriteLine(arr.Count());
}
}
public class GenericObject {
public int i = 0;
}
字典显然不像我希望的那样将值存储为引用。那么C#还有什么其他技术?或者这根本不可能?同样不确定0
0
会导致多少问题,所以我不敢走这条路。
答案 0 :(得分:1)
虽然我认为有解决此问题的更好方法,但是可以做到。
存储List<object>
而不是存储which isn't compatible和List<T>
的{{1}}引用。在object
中使用静态值来保存Base
,以便所有派生类都有一个Dictionary
。
Dictionary
PS另外,在使用public static void Main() {
var d = new Derived();
d.CheckCollection("d before AddElement");
d.AddElement(new GenericObject { i = 2 });
d.CheckCollection("d after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
var d2 = new Derived2();
d2.CheckCollection("d2 before AddElement");
d2.AddElement(new GenericObject2 { i = 4 });
d2.AddElement(new GenericObject2 { i = 5 });
d2.CheckCollection("d2 after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
}
public class Base {
static Dictionary<Type, object> ListReferences = new Dictionary<Type, object>();
public static int ListCount => ListReferences.Count();
protected ReadOnlyCollection<T> RegisterList<T>() {
var managedList = new List<T>();
ListReferences.Add(typeof(T), managedList);
return managedList.AsReadOnly();
}
public void AddElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Add(obj);
}
public void RemoveElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Remove(obj);
}
}
public class Derived : Base {
ReadOnlyCollection<GenericObject> roc;
public Derived() {
roc = RegisterList<GenericObject>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class Derived2 : Base {
ReadOnlyCollection<GenericObject2> roc;
public Derived2() {
roc = RegisterList<GenericObject2>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class GenericObject {
public int i = 0;
}
public class GenericObject2 {
public int i = 0;
}
时,请勿使用“数组”来命名方法和变量。
答案 1 :(得分:0)
您编写的以下代码会在创建列表时复制列表-因此无论之后添加到列表中的内容如何,列表始终为空。
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
这是您应该如何编写代码以获取所需内容的方法:
public static void Main()
{
Derived d = new Derived();
Console.WriteLine(d.AsReadOnly().Count);
d.AddElement(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class Base<T>
{
List<T> _items = new List<T>();
public ReadOnlyCollection<T> AsReadOnly()
{
return Array.AsReadOnly(_items.ToArray());
}
public void AddElement(T obj)
{
_items.Add(obj);
}
public void RemoveElement(T obj)
{
_items.Remove(obj);
}
}
public class Derived : Base<GenericObject>
{
}
public class GenericObject
{
public int i = 0;
}
输出:
0 1
现在,值得考虑的是List<T>
已经有一个AsReadOnly()
方法,因此您可以简单地编写以下代码:
public static void Main()
{
var d = new List<GenericObject>();
Console.WriteLine(d.AsReadOnly().Count);
d.Add(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class GenericObject
{
public int i = 0;
}
那也行。
在这里,您应该这样做以一次容纳多个列表。不需要继承。
public static void Main()
{
Repository r = new Repository();
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
r.AddElement<GenericObject>(new GenericObject { i = 2 });
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
}
public class Repository
{
private Dictionary<Type, object> _references = new Dictionary<Type, object>();
private void Ensure<T>()
{
if (!_references.ContainsKey(typeof(T)))
{
_references[typeof(T)] = new List<T>();
}
}
public ReadOnlyCollection<T> AsReadOnly<T>()
{
this.Ensure<T>();
return (_references[typeof(T)] as List<T>).AsReadOnly();
}
public void AddElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Add(obj);
}
public void RemoveElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Remove(obj);
}
}
public class GenericObject
{
public int i = 0;
}
答案 2 :(得分:-1)
在您的基类中(或封装类,如果您选择那样的话):
protected ReadOnlyCollection<T> GetSnapshot<T>() {
return Array.AsReadOnly(ArrayReferences[typeof(T)].Select(s => (T)s).ToArray());
}
然后,您还需要添加其他方法来查看数据,例如获得计数:
protected int GetCount<T>() {
return ArrayReferences[typeof(T)].Count;
}