2011-01-09 10 views
14

Mam problem ze zrozumieniem, jak działają ograniczenia ogólne. Chyba brakuje tu czegoś ważnego. Załączam moje pytania w komentarzach i będę wdzięczny za wyjaśnienia.Ogólne ograniczenie na T, aby typ odniesienia i typ wartości jednocześnie?

//1st example: 

class C <T, U> 
    where T : class 
    where U : struct, T 
{ 
} 
//Above code compiles well, 
//On first sight it looks like U might be reference type and value type 
//at the same time. The only reason I can think of, is that T may be an 
//interface which struct can implement, Am I correct? 

//2nd example 

class CC<T, U> 
    where T : class, new() 
    where U : struct, T 
{ 
} 

//I added also a reguirement for parameterless constructor 
//and, much to my surprise, it still compiles what is 
//a bit inexplicable for me. 
//What 'U' would meet the requirement to be 
//value type, reference type and have a contructor at the same time? 

Odpowiedz

12

Nie ma w tym nic złego. Przyjrzyjmy się definicji constraints on the type parameters:

  • T : class - Argument type T musi być typem odniesienia, w tym jakiejkolwiek klasy, interfejsu, delegata lub typu tablicy.
  • U : struct - Argument typu U musi być typem wartości.
  • U : T - Argument type U musi być albo wywodzą się z klasy T.

Więc wszystko co musisz zrobić, to znaleźć typ wartości, który wynika z rodzaju odniesienia. Na początku, że może wydawać się niemożliwe, ale jeśli uważasz, że nieco trudniej będzie pamiętać, że wszystkie kodowanym wywodzą się z klasy object, więc to działa dobrze dla obu swoich przykładach:

new C<object, int>(); 

Jeśli jednak zamienić struct i class następnie nie skompiluje:

// Error - Type parameter 'T' has the 'struct' constraint so 'T' 
//   cannot be used as a constraint for 'U' 
class C<T, U> 
    where T : struct 
    where U : class, T 
{ 
} 
+1

Tak? i ? Podałeś go dla T, który byłby zgodny z konstruktorem obiektów. W porządku. –

+0

Tak, masz rację, przeczytałem źle. @Mark Byers powiedziałeś, że wszystkie structs pochodzą z 'object'. SO Jeśli miałbym 'class CS gdzie T: class {}' Code like 'CS obj = new CS ();' nie działałoby, podczas gdy 'DateTime' można rzutować na obiekt. – nan

+0

@Andrzej Nosal: Tak, ponieważ ograniczenie "T: klasa" nie oznacza, że ​​* T można rzutować na obiekt *. Oznacza to * T musi być typem referencyjnym *. DateTime nie jest typem referencyjnym. –

Powiązane problemy