#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/