Поддерживает .Сеть поддерживает дженерики с карри?

#c# #.net #generics #currying

#c# #.net #дженерики #каррирование

Вопрос:

Предположим, у нас есть вложенный универсальный класс:

 public class A<T> {
    public class B<U> { }
}
  

Здесь, typeof(A<int>.B<>) по сути, это универсальный класс с двумя параметрами, где привязан только первый.

Если у меня есть один класс с двумя параметрами

 public class AB<T, U> { }
  

Есть ли способ ссылаться на « AB с T=int и U оставаясь открытым»? Если нет, является ли это ограничением C # или ограничением CLR?

Комментарии:

1. Можно ли это сделать с типами в F #?

2. Если вы спрашиваете меня, я понятия не имею… На самом деле я никогда не использовал F # какое-либо время.

3. Под «каррированным» вы подразумеваете «частично закрытый»?

4. Продолжая поиск в Google, я нашел это сообщение в блоге: lostechies.com/jimmybogard/2009/09/01 /…

Ответ №1:

По-видимому, это невозможно сделать на C #, вы должны указать либо оба параметра типа, либо ни одного.

И, похоже, это также не поддерживается CLR, A<int>.B<> и A<string>.B<> относится к тому же типу:

 Type t1 = typeof(A<int>).GetNestedType("B`1");
Type t2 = typeof(A<string>).GetNestedType("B`1");
// t1.Equals(t2) is true
  

Заключающий тип обоих типов — A<> (открытый универсальный тип)

РЕДАКТИРОВАТЬ: дальнейшее тестирование показывает, что typeof(A<int>.B<string>) на самом деле это универсальный тип arity 2, не вложенный универсальный тип arity 1… typeof(A<int>.B<string>).GetGenericArguments() возвращает массив с помощью typeof(int) и typeof(string) . Таким образом, typeof(A<int>.B<>) фактически было бы эквивалентно (A.B)<int, > , который не поддерживается (универсальный тип не может быть частично закрыт)

Комментарии:

1. Ваше наблюдение верно. Под прикрытием C<T>.D<U> — это просто «C.D»<T, U>. Способ представления C # как C<T>.D<U> — это просто удобная фикция.

2. @Eric, спасибо за подтверждение. Я надеялся, что вы увидите этот вопрос и прольете на него некоторый свет… Это могло бы стать хорошей темой для поста в блоге, если у вас закончились идеи 😉

3. Вы, конечно, правы. Моя ошибка заключалась в предположении, что это typeof(A<int>.B<>) было бы законно — я знал, что это A<T>.B<U> реализовано как A.B<T, U> , что означает, что typeof(A<int>.B<>) на самом деле было бы A.B<int, > то, что, казалось, не должно быть законным.

Ответ №2:

Это то, что вы имеете в виду?

    class AB<T, U>
   {
      protected T t;
      U u;
   }

   class C<U> : AB<int, U>
   {
      public void Foo()
      {
         t = 5;
      }
   }
  

Комментарии:

1. @downvoter: поговори со мной. Хотели бы вы увидеть выходные данные reflector, выдержку из спецификации C #, что-нибудь еще?

2. Похоже, что OP запрашивает экземпляр Type объекта, который выражает что-то вроде typeof(AB<int,>) .

Ответ №3:

вы можете использовать Func<int,int> generic для передачи нескольких параметров в виде одной функции, возвращающей тип. Curried many для передачи множества аргументов в качестве одного параметра.

  [Fact]
    public async Task TestCurried()
    {
        Func<int, Func<int, int>> curried = x => y => x   y;
        int sum = curried(1)(3);
        Assert.Equal(sum.ToString(), "4");
    }
see
https://blog.tchatzigiannakis.com/generics-as-super-functions/