Lister les interfaces implémentées par un Type
|
// le type de gauche doit être plus générique que celui de droite.
Type[] types = typeof(CC).GetInterfaces(); // retourne Type[1] avec II à l'intérieur
// test si CC implémente II, retourne le Type II si c'est le cas, sinon retourne null
Type type = typeof(CC).GetInterface("II");
interface II { }
class CC : II { }
|
Tester si un Type hérite d'un autre Type
|
// le type de gauche doit être plus générique que celui de droite.
bool b = typeof(II).IsAssignableFrom(typeof(CC));
// fais appel à IsSubclassOf et à GetInterfaces si le type de gauche est une interface
// Pour les classes seulement
// remonte récursivement à l'aide de la propriété BaseType
bool b = typeof(CC2).IsSubclassOf(typeof(CC));
interface II { }
class CC : II { }
class CC2 : CC { }
|
Tester si un objet est compatible avec un Type
|
C2 c2 = new C2();
bool b = c2 is II; // fonctionne avec les classes et les interfaces
interface II { }
class C1 : II { }
class C2 : C1 { }
|
Type to / from String
|
Type CCType = typeof(CC);
string typeString = type.AssemblyQualifiedName;
// CC
Type type = Type.GetType(typeString);
|
Valeur par défaut
Si c'est un type valeur, il faut créer une instance qui sera la valeur par défaut.
Si c'est un type référence, la valeur par défaut est null.
|
Type type;
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
|
|
// Boxing: convertir un type valeur en type object ou type interface implémenté par le type valeur.
// Créé une nouvelle instance d'object sur le tas (heap) et copie la valeur dans ce nouvel objet.
int i = 123;
object o = i; // implicit
// Unboxing
object o = 123;
i = (int)o; // explicit
// Unbox null créé une NullReferenceException.
// Unbox une référence vers un type valeur non compatible créé une InvalidCastException.
|
|
C1 c1 = new C2();
// Préfix cast seul. Intérêt: lever une exception contenant des infos utiles
try
{
C3 c3 = (C3)c1;
}
// Unable to cast object of type 'C2' to type 'C3'.
catch (InvalidCastException ex)
{ }
// is: on effectue le test, puis le cast, ce qui est couteux.
if (c1 is C2)
{
C2 c2 = (C2)c1;
}
// as: 5 fois plus rapise qu'un préfixe cast
// pas de distinction entre un objet null et une erreur de cast
C2 c2 = c1 as C2;
if (c2 != null)
{ }
// Nouvelle écriture VS 2017
if (c1 is C2 c2)
{ }
class C1 { }
class C2 : C1 { }
class C3 : C2 { }
|
Types de base
Type
|
Min
|
Max
|
Size
|
.NET Framework type
|
sbyte |
-128 |
127 |
Signed 8-bit integer |
System.SByte
|
byte |
0 |
255 |
Unsigned 8-bit integer |
System.Byte
|
char |
U+0000 |
U+ffff |
Unicode 16-bit character |
System.Char
|
short |
-32768 |
32767 |
Signed 16-bit integer |
System.Int16
|
ushort |
0 |
65535 |
Unsigned 16-bit integer |
System.UInt16
|
int |
-2,147,483,648 |
2,147,483,647 |
Signed 32-bit integer |
System.Int32
|
uint |
0 |
4,294,967,295 |
Unsigned 32-bit integer |
System.UInt32
|
long |
–9,223,372,036,854,775,808 |
9,223,372,036,854,775,807 |
Signed 64-bit integer |
System.Int64
|
ulong |
0 |
18,446,744,073,709,551,615 |
Unsigned 64-bit integer |
System.UInt64
|
float Pécision 7 digits |
-3.4 × 10^38 |
+3.4 × 10^38 |
32-bit |
System.Single
|
double Pécision 15-16 digits |
±5.0 × 10^−324 |
±1.7 × 10^308 |
64-bit |
System.Double
|
decimal Pécision 28-29 significant digits |
(-7.9 x 10^28 to 7.9 x 10^28) / (10^0 to 28) |
|
128-bit |
System.Decimal
|
Dépassement / overflow
|
int i = 2147483647;
i + 1; // -2147483648
// somme de int stockés dans un long
int[] myArray;
long totalSum = myArray.Sum(e => (long)e);
|
|
- Les types valeur ne peuvent pas contenir la valeur null.
- Chaque type valeur possède une valeur par défaut.
- Stockés dans la stack (sauf boxed, champs d'une classe, lambda expression)
- plus rapide, moins couteux en place et pas de gestion par le GC.
|
- Structures
- Énumérations
- Types numériques
|
Stockés dans la heap |
string est un type référence mais se comporte comme un type valeur pour les comparaisons.
|
// Define some strings:
string a = "hello";
string b = String.Copy(a);
string c = "hello";
// l'opérateur == compare les référence des types références
// comme string est un type référence, il devrait comparer les références
// mais pour faciliter les choses, l'opérateur == compare les valeurs des string
if (a == b) // true
if (a.Equals(b)) // true
// Pour comparer les références des string
if ((object)a == (object)b) // false
if (Object.ReferenceEquals(a, b)) // false
// Attention si 2 string ont la même valeur (a et c), ils pointeront vers la même référence
if ((object)a == (object)b) // true
if (Object.ReferenceEquals(a, b)) // true
|
Passage de types valeur par valeur
|
var i = 1;
SetTo5(i);
// i est toujours égal à 1
// le paramètre est passé par copie car c'est un type valeur
void SetTo5(int j)
{
// on ne modifie pas i mais une une copie de i
j = 5;
}
|
Passage de types valeur par référence
|
var i = 1;
SetTo5(ref i);
// i est égal à 5
// le paramètre est passé par référence grace au mot clé ref
void SetTo5(ref int j)
{
// on modifie i car c'est sa référence qui a été passée en paramètre
j = 5;
}
|
Passage de types référence par valeur
|
class MaClasse
{
public int MyProperty { get; set; }
}
var c = new MaClasse() { MyProperty = 1 };
SetMyPropertyTo5(c);
// c.MyProperty est égal à 5
// le paramètre est passé par référence car il est de type référence (class)
// m contient une copie de la référence sur c
void SetMyPropertyTo5(MaClasse m)
{
// on utilise la copie de la référence vers c pour modifier une de ses propriétés
m.MyProperty = 5;
// on perd la copie de la référence sur c au profit de la référence sur le nouvel objet.
// c ne sera donc pas modifié
m = new MaClasse() { MyProperty = 55 };
}
|
Passage de types référence par référence
|
var c = new MaClasse() { MyProperty = 1 };
SetMyPropertyTo5(ref c);
// MyProperty est égal à 55
// le paramètre est passé par référence car il est de type référence (class)
void SetMyPropertyTo5(ref MaClasse m)
{
m.MyProperty = 5;
// l'objet m est réalloué à l'aide de l'opérateur new.
m = new MaClasse() { MyProperty = 55 };
}
|