Esta é uma solução significativamente mais eficiente que as outras postadas aqui, especialmente a solução principal:
bool isSubset = t2.All(elem => t1.Contains(elem));
Se você puder encontrar um único elemento em t2 que não esteja em t1, saberá que t2 não é um subconjunto de t1. A vantagem desse método é que ele é feito no local, sem alocar espaço adicional, ao contrário das soluções usando .Except ou .Intersect. Além disso, esta solução pode quebrar assim que encontrar um único elemento que viole a condição do subconjunto, enquanto os outros continuam pesquisando. Abaixo está a forma longa ideal da solução, que é marginalmente mais rápida em meus testes do que a solução abreviada acima.
bool isSubset = true;
foreach (var element in t2) {
if (!t1.Contains(element)) {
isSubset = false;
break;
}
}
Fiz algumas análises rudimentares de desempenho de todas as soluções e os resultados são drásticos. Essas duas soluções são cerca de 100x mais rápidas que as soluções .Except () e .Intersect () e não usam memória adicional.