簡體   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