C# 从泛型数组返回引用
我有一个类,它包含C# 从泛型数组返回引用,c#,generics,.net-core,C#,Generics,.net Core,我有一个类,它包含组件库的列表组件子类组件库 public abstract class ComponentBase { public Type Type; public dynamic Value; public uint EntityID; } public class Component<T> : ComponentBase { public new Type Type;
组件库的列表<代码>组件
子类组件库
public abstract class ComponentBase
{
public Type Type;
public dynamic Value;
public uint EntityID;
}
public class Component<T> : ComponentBase
{
public new Type Type;
public new T Value;
public new uint EntityID;
}
我度过了一个漫长的夜晚,我觉得有一个简单的解决办法,但我真的找不到。任何帮助都将不胜感激。从根本上说,代码的问题在于您试图返回对对象的错误成员的引用。当您实际需要具有
T
类型的成员时,您返回的是带有dynamic
类型的成员
您的原始示例相当于这个更简单的示例:
类基
{
公共int Id;
公共动态价值;
公共基(int-id,动态值)
{
Id=Id;
价值=价值;
}
公共重写字符串ToString()=>$“{{Id:{Id},值:{Value}”;
}
派生类:基
{
公共新int Id;
公共新价值观;
公共派生(int-id,T-value):基(id,value){}
}
静态void Main(字符串[]参数)
{
派生[]数组=新[]
{
新派生(0,“零”),
新衍生(1,“一”),
新衍生(2,“两”),
};
ref string valueRef=ref GetElement(数组,1);
valueRef=“三”;
WriteLine(string.Join(Environment.NewLine,array));
}
私有静态ref T GetElement(基[]数组,int-id)
{
//错误CS8151:返回表达式的类型必须为“T”,因为此方法通过引用返回
返回ref array.Where(x=>x.Id==Id).First().Value;
}
问题很简单,您试图返回基类字段,它的类型是dynamic
,而不是T
要解决此问题,您需要强制转换对象,以便从派生类型获取字段:
private static ref T GetElement(Base[]数组,int-id)
{
返回ref((派生的)array.Where(x=>x.Id==Id.First()).Value;
}
或者,在您最初的示例中:
public ref T getComponentEntity(实体),其中T:new()
{
返回ref((Component)components.Where(x=>x.EntityID==entity.Id&&x.Type==typeof(T)).First().Value;
}
现在,所有这些都表明:我敦促你们重新思考设计。可能您省略了一些初始化基本值
字段的代码,这些代码与派生的值
字段相同。但即使是这样(这已经够浪费的了),也没有什么可以阻止这些字段以后被不同地分配。这不仅是浪费,而且如果对象中的每个值都有两个副本,特别是当这些值不是只读的时候,这很可能会导致bug
应不惜一切代价避免成员隐藏(即使用数据结构中的new
关键字)。这只会导致混乱,几乎肯定会导致以后出现大量难以发现、难以修复的bug。您在这里遇到的问题只是冰山一角,但这是一个很好的例子,说明当一个对象有两个同名的不同成员时,事情会变得多么混乱
此外,ref返回值应尽量少用,且仅在绝对必要时使用(例如,仅使用ref返回即可解决的关键性能问题)。当然,你的问题中缺少了上下文,所以也许你确实有一个很好的理由在这里使用该功能。但是,仅根据当前代码中的名称,我认为您可以让代码正常工作,而不会出现代码中的任何异常(成员隐藏和ref返回值)。Wow。。。。。我实际上说不出话来。这个答案令人难以置信!为了回答您的一些问题,我使用了成员隐藏作为临时解决方案,这样我就可以将
组件
组织到一个单数类型的列表中,其中T
有所不同<之所以使用code>ref值,是因为我需要在这些变量来源于它们来自的数组之后修改它们。我非常感谢你的回答。你没有忽视或放下我的编码方式,而是对我的问题进行了真正的破解,帮助我找到了解决方案,并向我展示了我应该如何写这篇文章。谢谢!
public class ComponentDatabase
{
ComponentBase[] components;
private int componentIndex;
public T AddComponentToEntity<T>(T component, Entity entity) where T : new()
{
var x = component != null ? component : new T();
var comp = new Component<T> { EntityID = entity.Id, Type = typeof(T), Value = x };
components[componentIndex++] = comp;
return x;
}
public ref T GetComponentOnEntity<T>(Entity entity) where T : new()
{
return ref components.Where(x => x.EntityID == entity.Id && x.Type == typeof(T)).First().Value;
}
}