Making method as generic causes error: The type 'T' cannot be used as type parameter 'T' in the generic type or method

Advertisements

I created a method GetArticlePriceDefinedInErpPricePolicyAsync, previously I had 4 versions of this method which was not good for maintance, one change caused editing 4 methods which were actually same, and it was bad concept since I would keep identical code x4.

The reason why I would like to write this method as generic is because there are 4 different classes that are using this method (webShopArticles can be 4 different classes).

Purpose of this method is to receive list of some Dto’s and to return modified prices.

And solution to this could be to create this method as a generic so I could have only one method in my app instead of 4 same methods.

It would be much more easy to maintain the app etc.

Here is my code:

public async Task<List<T>> GetArticlePriceDefinedInErpPricePolicyAsync<T>(List<T> webShopArticles, Guid? externalCompanyId, CancellationToken cancellationToken)
{
    var externalArticleIds = webShopArticles
        .Where(x => GetPropertyValue<Guid?>(x, "ErpArticleId").HasValue)
        .Select(x => GetPropertyValue<Guid>(x, "ErpArticleId"))
        .ToArray();
        
    var pricePolicyItems = new List<PricesRelatedToPricePolicy>();

    var articlesFromPricePolicy = await _dbContext.ErpPricePolicyItems
        .Where(x => externalArticleIds.Contains(GetPropertyValue<Guid>(x, "ExternalArticleId")))
        .Select(x => new PricesRelatedToPricePolicy
        {
            Id = x.Id,
            ErpArticleId = GetPropertyValue<Guid>(x, "ExternalArticleId"),
            Priority = x.Priority,
            PolicyTypeEnum = x.PolicyType,
            Price = x.Price,
            Discount1 = x.Discount1,
            Discount2 = x.Discount2,
            Discount3 = x.Discount3
        })
        .ToArrayAsync(cancellationToken);

    pricePolicyItems.AddRange(articlesFromPricePolicy);
    
    if (!pricePolicyItems.Any())
        return webShopArticles;
  
    ArticleMatching(webShopArticles, articlesFromPricePolicy);

    return webShopArticles;
}


private List<T> ArticleMatching<T>(List<T> articles, PricesRelatedToPricePolicy[] articlesDefinedInPricesPolicy) where T : IErpPricePolicySyncProps
{
    if (articlesDefinedInPricesPolicy[0] == null)
        return articles;

    foreach (var item in articles.Where(x => !x.MatchedPP.HasValue && x.ExternalSytemArticleId.HasValue))
    {
        var articleDefinedInPolicyPrice = articlesDefinedInPricesPolicy
            .Where(x => x.ExternalSytemArticleId.HasValue && (x.ExternalSytemArticleId == item.ExternalSytemArticleId))
            .FirstOrDefault();

        item.Price = CalculateArticlePriceBasedOnPricePolicy(articleDefinedInPolicyPrice, item);
        item.MatchedPP = articlesDefinedInPricesPolicy.Any(x => item.ExternalSytemArticleId.HasValue && x.ExternalSytemArticleId.Value == item.ExternalSytemArticleId.Value);
    }

    return articles;
}

But I am getting this error:

Error CS0314 The type ‘T’ cannot be used as type parameter ‘T’ in the generic type or method ‘PricePolicyCalculationService.ArticleMatching(List, PricesRelatedToPricePolicy[])’. There is no boxing conversion or type parameter conversion from ‘T’ to ‘Common.Dtos.Interfaces.IErpPricePolicySyncProps’.

IErpPricePolicySyncProps is interface that inheriting classes that will use this generic method

 public interface IErpPricePolicySyncProps
 {
        public Guid? ErpArticleId { get; set; }
        public Guid? ErpCategoryId { get; set; }
        public Guid? ErpSubCategoryId { get; set; }
        public Guid? ErpBrandId { get; set; }
        public decimal Price { get; set; }
        public bool? MatchedPP { get; set; }
 }

Thanks in advance,
Cheers

>Solution :

The ArticleMatching method expects the object you pass in to implement the IErpPricePolicySyncProps interface. If you look at it, it will be something like this:

public void ArticleMatching<T>(List<T> articles, ...)
    where T : IErpPricePolicySyncProps

So to fix this, you also need to mark your method in the same way:

public async Task<List<T>> GetArticlePriceDefinedInErpPricePolicyAsync<T>(List<T> webShopArticles, Guid? externalCompanyId, CancellationToken cancellationToken)
    where T : IErpPricePolicySyncProps
{
    ...
}

Leave a ReplyCancel reply