我遇到了一个问题,它采用了标准的输入组合,但有几种算法('处理器')可以解决它。输出是布尔值。每个处理器仅对一个特定场景有效,并且永远不会有多个处理器有效。
每个处理器通过提供一些初始输入来确定它是否有效。如果它是有效的,那么它会根据这些初始输入计算一些信息并存储它 - 因为该信息在最终过程中很有用。然后,如果它有效,则向处理器提供附加输入并返回输出。
如果没有处理器有效,则给出默认答案。
因此算法在伪代码中是这样的:
process(inputs)
for each processor
determine validity and get data
if valid
use data to output result
end if
end for
output default result
end
这是一个C#示例,它在语法上无效。它只是一个例子,在现实生活中,输入比字符串和整数更复杂。第二个输入的计算(在设计示例中为int i)在循环内重复执行,而第一个输入仅计算一次 - 因此将过程是否与处理器的结果有效分开。作为使用IEnumerable的替代方法,我们可以拥有一个数组或处理器列表。
public class ProcessController
{
public static IEnumerable<Processor<X>> GetProcessors<X>() where X: ProcessorInfo
{
yield return new ProcessorA();
yield return new ProcessorB();
}
public static bool Process<X>(String s, int i) where X : ProcessorInfo
{
foreach (Processor<X> processor in GetProcessors<X>())
{
X x = (X) processor.GetInfoIfCanProcess(s);
if (x != null)
{
return processor.GetResult(x, i);
}
}
return false;
}
}
public abstract class Processor<T> where T: ProcessorInfo
{
public abstract T GetInfoIfCanProcess(String s);
public abstract bool GetResult(T info, int i);
}
public interface ProcessorInfo
{
bool IsValid();
}
public class ProcessorA: Processor<ProcessorA.ProcessorInfoA>
{
public class ProcessorInfoA: ProcessorInfo
{
public bool IsValid()
{
//do something!
}
}
public override ProcessorInfoA GetInfoIfCanProcess(string s)
{
//do something!
}
public override bool GetResult(ProcessorInfoA info, int i)
{
//do something!
}
}
public class ProcessorB : Processor<ProcessorB.ProcessorInfoB>
{
public class ProcessorInfoB : ProcessorInfo
{
public bool IsValid()
{
//do something!
}
}
public override ProcessorInfoB GetInfoIfCanProcess(string s)
{
//do something!
}
public override bool GetResult(ProcessorInfoB info, int i)
{
//do something!
}
}
我在GetProcessors方法中遇到语法错误:无法将类型Play.ProcessorA
隐式转换为Play.Processor<X>
。我怎么能绕过这个?
答案 0 :(得分:2)
解决此问题的最简单方法是使用OfType
:
private static IEnumerable<object> GetProcessors()
{
yield return new ProcessorA();
yield return new ProcessorB();
}
public static IEnumerable<Processor<X>> GetProcessors<X>() where X: ProcessorInfo
{
return GetProcessors.OfType<Processor<X>>();
}
由于Processor<X>
是不变的,因此您无法使用常见类型,并且由于在方法之外选择了X
,因此您需要使用动态类型检查。
答案 1 :(得分:2)
您正在尝试使用泛型将处理器类及其处理器信息类耦合,这是有问题的。你最终会得到一个松散的姿势,你只需将物体投射到它们应该的位置,而不是让仿制品确保类型是正确的。
我建议你通过将信息存储在类本身中来避免这个问题。运行处理器的代码不必知道处理器使用的信息,只需要知道处理器是否有效。
返回布尔值而不是ProcessorInfo对象,并将相关数据保留在Processor对象中。如果处理器有效,则它具有所需的数据。如果没有,当你继续尝试下一个处理器时,它将与第一步中获得的数据一起消失。