繁体   English   中英

泛型方法类型转换

[英]Generic method type conversion

我有这样的事情:

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>{
      ...
   }
}

FindParameterValue 方法是我遇到问题的地方。 它从列表中获取特定类型的第一个参数并返回其值。 现在我收到此错误: 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>'. . 我只想提供一个派生的 class,它实现了 Parameter<IArgument>。 我可以通过这样做来避免它:

public decimal FindParameterValue<T,U>() where T : Parameter<U> where U : class, IArgument

这使我将其称为:

FindParameterValue<ParameterA, ArgumentA>();

但我想只用“ParameterA”类型来调用它。

抱歉,如果这已经在某个地方解决了。

提前致谢!

约束使用实际类型。 如果规则如您所描述的那样有效,则很有可能编写:

void MyMethod<T>(T myParameter) where T : List<IFruit>{
    myParameter.Add( new Banana() );
}
....
MyMethod(new List<Apple>());

你最终会得到一个包含香蕉的苹果列表。 您可以通过将抽象参数 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>();
    }
}

问题是Parameter<T>的每个定义都是不同的类型。 如果您从抽象 class 中删除 generics,您将解决您的问题。 是否有理由Parameter需要是通用的? 你可以改用模式匹配吗?

虽然意图并不明确,但请尝试以下代码:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM