簡體   English   中英

如何限制泛型方法的嵌套泛型類型

[英]How to constrain nested generic types of a generic method

我正在嘗試創建一種基於給定泛型從數據庫返回數據的方法。

接口:(此定義編譯)

public interface IOrderPosition<TOrder, TArticle, TOrderPosition>
  where TOrder : IOrder
  where TArtile : IArticle
  where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>
{
  long? id { get; set; }
  TOrder order { get; set; }
  TArtile article { get; set; }
  List<TOrderPosition> subPositions { get; set; }
}

一個可能的具體實現:(此定義編譯)

public class OrderPosition : IOrderPosition<Order, Article, OrderPosition>
{
  public long? id { get; set; }
  public Order order { get; set; }
  public Article article { get; set; }
  public List<OrderPosition> subPositions { get; set; }
}

嘗試基於接口編寫通用方法:(此定義不編譯)

public List<TOrderPosition> GetOrderPositionOfOrder<TOrderPosition>(long? id) 
  where TOrder : IOrder
  where TArticle : IArticle
  where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>
{
  ..
}

錯誤:

'DataSourceOrder.GetOrderPositionOfOrder<TOrderPosition>()' does not define type parameter 'TOrder'
'DataSourceOrder.GetOrderPositionOfOrder<TOrderPosition>()' does not define type parameter 'TArticle'
The type or namespace name 'TOrder' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'TArticle' could not be found (are you missing a using directive or an assembly reference?)

要這樣使用:

List<OrderPosition> positions = GetOrderPositionOfOrder<OrderPosition>(5);
List<TransferOrderPosition> transferPositions = GetOrderPositionOfOrder<TransferOrderPosition>(5);

題:

為什么要為接口而不是方法進行編譯?

我希望兩者都能奏效或都會失敗。 我假設編譯器可以從為TOrderPosition給出的類型推斷TOrder和TArticle的類型,而TOrderPosition定義了商品和訂單的具體類型。

我想知道為什么會發生這種情況,以及是否以及如何解決該問題而不必顯式指定所有類型。

為什么要為接口而不是方法進行編譯?

那么,您聲明TOrderTArticleIOrderPosition界面,但不是在GetOrderPositionOfOrder方法。

您需要在方法聲明中聲明這些通用參數:

public List<TOrderPosition> GetOrderPositionOfOrder<TOrder, TArticle, TOrderPosition>(long? id)
    where TOrder : IOrder
    where TArticle : IArticle
    where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>
{
    ...
}

並這樣稱呼它:

var list = GetOrderPositionOfOrder<Order, Article, OrderPosition>(5);

但是,如果您要像這樣調用GetOrderPositionOfOrder

var list = GetOrderPositionOfOrder<OrderPosition>(5);

您可以在TOrderTArticle中使IOrderPosition協變:

interface IOrderPosition<out TOrder, out TArticle, TOrderPosition>
    where TOrder : IOrder
    where TArticle : IArticle
    where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>
{
    long? id { get; set; }
    TOrder order { get; }
    TArticle Article { get; }
    List<TOrderPosition> subPositions { get; set; }
}

請注意, OrderArticle必須是只允許使用getter的屬性(但是OrderPosition這些屬性可以具有set訪問器)。

和方法:

public List<TOrderPosition> GetOrderPositionOfOrder<TOrderPosition>(long? id)
    where TOrderPosition : IOrderPosition<IOrder, IArticle, TOrderPosition>
{
    ...
}

這樣做可以像GetOrderPositionOfOrder<OrderPosition>(5)那樣進行調用。

看一下錯誤:

'DataSourceOrder.GetOrderPositionOfOrder()'未定義類型參數'TOrder''DataSourceOrder.GetOrderPositionOfOrder()'未定義類型參數'TArtile'

您指的是不存在的類型參數。
您應該在方法中定義它們,就像在接口中定義它們的方式一樣:

public static List<TOrderPosition> GetOrderPositionOfOrder<TOrder, TArticle, TOrderPosition>(long? id)

這意味着調用該方法將很麻煩:

var positions = GetOrderPositionOfOrder<Order, Position, OrderPosition>(5);
var transferPositions = GetOrderPositionOfOrder<TransferOrder, TransferArticle, TransferOrderPosition>(5);

調用該方法時,必須提供所有類型參數,或者不提供任何類型參數(如果可以推斷出它們)。 就是那樣子。

在界面中,將其定義為接受3種類型的通用類型TOrder, TArticle, TOrderPosition ,因此您可以限制這些類型。

您的方法僅定義一個類型TOrderPosition ,並且編譯器無法從方法定義where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>的約束where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>推斷您需要其他類型的事實。

您需要做的就是以與對接口相同的方式定義通用方法上的所有類型:

public List<TOrderPosition> GetOrderPositionOfOrder<TOrder, TArticle, TOrderPosition>(long? id) 
 where TOrder : IOrder
 where TArticle : IArticle
 where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>
{
 ..
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM