Метод расширения Generi c вызывает перегрузку non-generi c и вызывает бесконечную рекурсию - PullRequest
0 голосов
/ 31 января 2020

Я использую пакет Microsoft.Extensions.Caching.Abstractions в своем решении. Этот пакет содержит интерфейс IDistributedCache. Также определен метод расширения со следующей сигнатурой: public static void Set(this IDistributedCache cache, string key, byte[] value)

В моем проекте я создал обобщенный метод расширения c Set <>, который принимает любой экземпляр класса, сериализует его и сохраняет как байт. []. К сожалению, это не работает и вызывает бесконечную рекурсию:

public static void Set<T>(this IDistributedCache cache, string key, T value) where T : class
{
    byte[] byteArray = value.ToByteArray();
    cache.Set(key, byteArray); // recursion call here, my generic method Set<byte[]> is called here instead of the non-generic version from Microsoft.Extensions.Caching.Abstractions
    // temporary workaround is to call: 
    // Microsoft.Extensions.Caching.Distributed.DistributedCacheExtensions.Set(cache, key, byteArray);
}

Я также создал похожий интерфейс и два метода расширения, таких как:

public interface IMyDistributedCache
{

}

public static class MyDistributedCacheExtensions
{
    public static void Set(this IMyDistributedCache cache, string key, byte[] value)
    {

    }
}
public static class MySecondDistributedCacheExtensions
{
    public static void Set<T>(this IMyDistributedCache cache, string key, T value) where T : class
    {
        byte[] byteArray = value.ToByteArray();
        cache.Set(key, byteArray); // works fine! no recursive calls!
    }
}

И .... это работает отлично! Нет рекурсивных вызовов, нет бесконечных l oop. Что тут происходит? В чем разница между моим IDistributedCache и IMyDistributedCache? Почему работает второй пример? Заранее спасибо.

1 Ответ

0 голосов
/ 31 января 2020

потому что во втором примере у вас есть метод (то же имя = set) с полностью определенным типом для параметра значения (байтовый массив). Компилятор ищет сигнатуру методов с наилучшим соответствием типов. Если метод имеет обобщенный тип c, он имеет приоритет 2.

см. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-methods

, если вы измените свой пример, чтобы следовать, он будет и в конечном итоге в бесконечном l oop:

public interface IMyDistributedCache
{

}

public static class MyDistributedCacheExtensions
{
    public static void Set(this IMyDistributedCache cache, string key, byte[] value)
    {

    }
}
public static class MySecondDistributedCacheExtensions
{
    public static void Set<T>(this IMyDistributedCache cache, string key, T value) where T : class
    {
        byte[] byteArray = value.ToByteArray();
        cache.Set<byte[]>(key, byteArray); //<<< endless loop
    }
}
...