Вы не можете, как заявили другие, но вы можете почти сделайте это.
Так все Tuple<...>
классов имеет подпись, как это:
public class Tuple<T1, ...> :
IStructuralEquatable,
IStructuralComparable,
IComparable,
ITuple
Все эти интерфейсы сохранить ITuple
является общедоступной (ITuple
внутренним интерфейс), так что вы можете попробовать крафт что-то вроде этого:
public interface ITupleKey<TKey>
where TKey : IStructuralEquatable, IStructuralComparable, IComparable
{
}
«Но подождите!», Вы говорите: «Как я могу быть уверен, что ничего другого не реализует эти интерфейсы?»
Ну, вы не можете.Но, как я уже сказал, это просто почти путь - к счастью, IStructuralEquatable
и IStructuralComparable
только (на уровне каркаса, естественно) используется в следующих типов:
System.Array
System.Tuple<T1>
System.Tuple<T1,T2>
System.Tuple<T1,T2,T3>
System.Tuple<T1,T2,T3,T4>
System.Tuple<T1,T2,T3,T4,T5>
System.Tuple<T1,T2,T3,T4,T5,T6>
System.Tuple<T1,T2,T3,T4,T5,T6,T7>
System.Tuple<T1,T2,T3,T4,T5,T6,T7,TRest>
Так что это довольно близко. Объедините это с проверкой времени выполнения, что TKey
действительно является некоторым вариантом Tuple
, и у вас может быть то, что вам нужно.
EDIT:
Некоторые основные использование:
public class Class1<TKey>
where TKey : IStructuralEquatable, IStructuralComparable, IComparable
{
}
// will compile
var classTup1 = new Class1<Tuple<int>>();
var classTup2 = new Class1<Tuple<int,int>>();
var classTup3 = new Class1<Tuple<int,int,int>>();
var classTup4 = new Class1<Tuple<int,int,int,int>>();
var classTup5 = new Class1<Tuple<int,int,int,int,int>>();
// won't compile
var badclassTup1 = new Class1<int>();
var badclassTup2 = new Class1<string>();
var badclassTup3 = new Class1<object>();
И, потому что я явно сошел с ума, давайте посмотрим, что здесь можно:
public class Class1<TKey>
where TKey : IStructuralEquatable, IStructuralComparable, IComparable
{
public Class1(TKey key)
{
Key = key;
TupleRank = typeof(TKey).GetGenericArguments().Count();
TupleSubtypes = typeof(TKey).GetGenericArguments();
Console.WriteLine("Key type is a Tuple (I think) with {0} elements", TupleRank);
TupleGetters =
Enumerable.Range(1, TupleRank)
.Select(i => typeof(TKey).GetProperty(string.Concat("Item",i.ToString())))
.Select(pi => pi.GetGetMethod())
.Select(getter => Delegate.CreateDelegate(
typeof(Func<>).MakeGenericType(getter.ReturnType),
this.Key,
getter))
.ToList();
}
public int TupleRank {get; private set;}
public IEnumerable<Type> TupleSubtypes {get; private set;}
public IList<Delegate> TupleGetters {get; private set;}
public TKey Key {get; private set;}
public object this[int rank]
{
get { return TupleGetters[rank].DynamicInvoke(null);}
}
public void DoSomethingUseful()
{
for(int i=0; i<TupleRank; i++)
{
Console.WriteLine("Key value for {0}:{1}", string.Concat("Item", i+1), this[i]);
}
}
}
Испытательный стенд:
var classTup1 = new Class1<Tuple<int>>(Tuple.Create(1));
var classTup2 = new Class1<Tuple<int,int>>(Tuple.Create(1,2));
var classTup3 = new Class1<Tuple<int,int,int>>(Tuple.Create(1,2,3));
var classTup4 = new Class1<Tuple<int,int,int,int>>(Tuple.Create(1,2,3,4));
var classTup5 = new Class1<Tuple<int,int,int,int,int>>(Tuple.Create(1,2,3,4,5));
classTup1.DoSomethingUseful();
classTup2.DoSomethingUseful();
classTup3.DoSomethingUseful();
classTup4.DoSomethingUseful();
classTup5.DoSomethingUseful();
Выход :
Key type is a Tuple (I think) with 1 elements
Key type is a Tuple (I think) with 2 elements
Key type is a Tuple (I think) with 3 elements
Key type is a Tuple (I think) with 4 elements
Key type is a Tuple (I think) with 5 elements
Key value for Item1:1
Key value for Item1:1
Key value for Item2:2
Key value for Item1:1
Key value for Item2:2
Key value for Item3:3
Key value for Item1:1
Key value for Item2:2
Key value for Item3:3
Key value for Item4:4
Key value for Item1:1
Key value for Item2:2
Key value for Item3:3
Key value for Item4:4
Key value for Item5:5
Каждый тип 'Tuple <>' имеет различное количество общих аргументов, и поэтому они являются разными типами. Вы не можете добавить ограничение для всех сразу. Есть ли причина, по которой 'TKey' * нуждается в ограничениях? – cdhowie
@cdhowie Я ответил на вопрос в вашем решении, но я отправлю его здесь «есть абсолютная причина, что он должен быть одним из классов кортежей, идея состоит в том, чтобы заставить TKey действовать как ключ с n параметрами, т. Е. T1, T2, T3, ..., Tn. " –