[英]Generic method type conversion
I have something like this:我有这样的事情:
interface IArgument{ ... }
class ArgumentA : IArgument{ ... }
abstract class Parameter<T> where T : class, IArgument{
...
abstract decimal GetValue(T args);
...
}
class ParameterA : Parameter<ArgumentA>{
override decimal GetValue(ArgumentA args){
...
}
}
abstract class Calculation{
List<Parameter<IArgument>> Parameters{get;set;}
decimal FindParameterValue<T>() where T : Parameter<IArgument>{
...
}
}
The method FindParameterValue is where I have a problem. FindParameterValue 方法是我遇到问题的地方。 It gets the first parameter of a specific type out of the list and returns its value.
它从列表中获取特定类型的第一个参数并返回其值。 Now I get this error:
Error CS0311 The type 'ParameterA' cannot be used as type parameter 'T' in the generic type or method 'Calculation.FindParameterValue<T>()'. There is no implicit reference conversion from 'ParameterA' to 'Parameter<IArgument>'.
现在我收到此错误:
Error CS0311 The type 'ParameterA' cannot be used as type parameter 'T' in the generic type or method 'Calculation.FindParameterValue<T>()'. There is no implicit reference conversion from 'ParameterA' to 'Parameter<IArgument>'.
Error CS0311 The type 'ParameterA' cannot be used as type parameter 'T' in the generic type or method 'Calculation.FindParameterValue<T>()'. There is no implicit reference conversion from 'ParameterA' to 'Parameter<IArgument>'.
. . I would like to just supply a derived class which implements Parameter< IArgument>.
我只想提供一个派生的 class,它实现了 Parameter<IArgument>。 I can avoid it by doing this:
我可以通过这样做来避免它:
public decimal FindParameterValue<T,U>() where T : Parameter<U> where U : class, IArgument
Which causes me to call it like:这使我将其称为:
FindParameterValue<ParameterA, ArgumentA>();
But I'd like to call it with just the 'ParameterA'-type.但我想只用“ParameterA”类型来调用它。
Sorry if this is already solved somewhere.抱歉,如果这已经在某个地方解决了。
Thanks in advance!提前致谢!
The constraint uses the actual types.约束使用实际类型。 If the rules worked as you describe it might very well be possible to write:
如果规则如您所描述的那样有效,则很有可能编写:
void MyMethod<T>(T myParameter) where T : List<IFruit>{
myParameter.Add( new Banana() );
}
....
MyMethod(new List<Apple>());
And you would end up with a list of apples that contains a banana.你最终会得到一个包含香蕉的苹果列表。 You can avoid this by changing the abstract Parameter class to a covariant interface, ie
您可以通过将抽象参数 class 更改为协变接口来避免这种情况,即
interface IArgument { }
class ArgumentA : IArgument {}
interface IParameter<out T> where T :IArgument{ }
class ParameterA : IParameter<ArgumentA>{}
class Calculation
{
void FindParameterValue<T>() where T : IParameter<IArgument>
{ }
void Test()
{
FindParameterValue<ParameterA>();
}
}
The problem is that every definition of Parameter<T>
is a different type.问题是
Parameter<T>
的每个定义都是不同的类型。 If you remove the generics from the abstract class you will solve your problem.如果您从抽象 class 中删除 generics,您将解决您的问题。 Is there a reason
Parameter
needs to be generic?是否有理由
Parameter
需要是通用的? Can you work with pattern matching instead?你可以改用模式匹配吗?
Although the intention isn't clear exactly, try the code below:虽然意图并不明确,但请尝试以下代码:
public interface IArgument { }
public class ArgumentA : IArgument
{
public decimal Value { get; }
}
public abstract class Parameter
{
public abstract decimal GetValue(IArgument args);
}
public class ParameterA : Parameter
{
public override decimal GetValue(IArgument args)
{
if (args is ArgumentA argA)
{
return argA.Value;
}
return 0m;
}
}
public abstract class Calculation
{
List<Parameter> Parameters { get; } = new List<Parameter>();
public decimal FindParameterValue<T>(IArgument argument) where T : Parameter
{
var item = Parameters.OfType<T>().FirstOrDefault();
if (item != null)
{
return item.GetValue(argument);
}
return 0m;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.