我试图从一个带有动态变量的继承抽象基类中调用一个方法,但它因溢出异常而失败。
可以在以下位置测试可运行版本(带有 bool 值): https://dotnetfiddle.net/hSfsZl
可以在以下位置找到崩溃的可运行版本(具有动态值): https://dotnetfiddle.net/qXlMZD
public static void Main(string[] args)
{
dynamic processed = true;
// this works though
//bool visible = true;
var data = new TemplateData<string>();
var dataProcessor = new TemplateDataProcessor<string>(data);
dataProcessor.Process(processed);
Console.WriteLine(data.Processed);
}
public class Data : IData
{
public bool Processed { get; set; }
}
public interface IData
{
bool Processed { get; set; }
}
public abstract class DataProcessorBase<TData, TDataBuilder>
where TDataBuilder : DataProcessorBase<TData, TDataBuilder>
where TData : IData
{
public TData Data { get; set; }
public DataProcessorBase(TData data)
{
Data = data;
}
public TDataBuilder Process(bool value)
{
Data.Processed = value;
return this as TDataBuilder;
}
}
public abstract class DataProcessor<TData, TDataBuilder> : DataProcessorBase<TData, TDataBuilder>
where TDataBuilder : DataProcessor<TData, TDataBuilder>
where TData : IData
{
public DataProcessor(TData data)
: base(data)
{
}
}
public interface ITemplateData<T> : IData
where T : class
{
string Template { get; set; }
}
public class TemplateData<T> : ITemplateData<T>
where T : class
{
public string Template { get; set; }
public bool Processed { get; set; }
}
public class TemplateDataProcessor<T> : DataProcessor<ITemplateData<T>, TemplateDataProcessor<T>>
//public class TemplateDataProcessor<T> : DataProcessorBase<ITemplateData<T>, TemplateDataProcessor<T>>
where T : class
{
public TemplateDataProcessor(ITemplateData<T> data)
: base(data)
{
}
}
使用 bool 值调用 dataProcessor.Process(processed);
按预期工作,但使用等于 true 的动态变量调用它会抛出异常。另外,从基础抽象类继承解决了这个问题
public class TemplateDataProcessor<T> : DataProcessorBase<ITemplateData<T>, TemplateDataProcessor<T>>
为什么这不起作用?此外,为什么从基类继承 - DataProcessorBase
- 即使使用动态值也能正常工作?以下破坏代码的继承有什么问题:
public abstract class DataProcessor<TData, TDataBuilder> : DataProcessorBase<TData, TDataBuilder>
是否可以通过满足以下所有要求来解决此问题:
- 不要将任何方法从
DataProcessorBase
移动到DataProcessor
类或更改它们的代码,例如不允许更改为Process(dynamic value)
。 - 将使用动态调用
dataProcessor.Process
,即不能强制 API 的最终用户使用 bool 而不是 dynamic。
最佳答案
这似乎是 .NET 本身的问题 - 在动态调度中,如调用堆栈所示:它只是重复
TypeManager.SubstTypeCore(type, pctx)
TypeManager.SubstTypeArray(taSrc, pctx)
TypeManager.SubstTypeCore(type, pctx)
AggregateType.GetBaseClass()
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
TypeManager.SubstTypeCore(type, pctx)
TypeManager.SubstTypeArray(taSrc, pctx)
TypeManager.SubstTypeCore(type, pctx)
AggregateType.GetBaseClass()
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
TypeManager.SubstTypeCore(type, pctx)
TypeManager.SubstTypeArray(taSrc, pctx)
TypeManager.SubstTypeCore(type, pctx)
AggregateType.GetBaseClass()
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
AggregateSymbol.getThisType()
SymbolTable.AddAggregateToSymbolTable(parent, type)
SymbolTable.LoadSymbolsFromType(originalType)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
SymbolTable.CreateInheritanceHierarchyList(type)
SymbolTable.PopulateSymbolTableWithName(name, typeArguments, callingType)
PopulateSymbolTableWithPayloadInformation(payload, callingType, arguments)
BindCore(payload, parameters, args, deferredBinding)
Bind(payload, parameters, args, deferredBinding)
BinderHelper.Bind(action, binder, args, arginfos, onBindingError)
CSharpInvokeMemberBinder.FallbackInvokeMember(target, args, errorSuggestion)
DynamicMetaObject.BindInvokeMember(binder, args)
InvokeMemberBinder.Bind(target, args)
DynamicMetaObjectBinder.Bind(args, parameters, returnLabel)
CallSiteBinder.BindCore<System.Action<System.Runtime.CompilerServices.CallSite, Program.TemplateDataProcessor<string>, object>>(site, args)
UpdateDelegates.UpdateAndExecuteVoid2<Program.TemplateDataProcessor<string>, object>(site, arg0, arg1)
Program.Main(args)
我会向 Microsoft 报告
关于c# - 使用动态值调用抽象基类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56269959/