Type

De Banane Atomic
Aller à la navigationAller à la recherche

Lister les interfaces implémentées par un Type

Csharp.svg
// 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

Csharp.svg
// 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

Csharp.svg
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

Csharp.svg
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.

Csharp.svg
Type type;
if (type.IsValueType)
{
    return Activator.CreateInstance(type);
}
return null;

Boxing / Unboxing

Csharp.svg
// 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.

Préfix cast, as, is

Csharp.svg
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

Csharp.svg
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 valeurs

  • 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.

Les types références

Stockés dans la heap
  • object
  • string
  • dynamic

string

string est un type référence mais se comporte comme un type valeur pour les comparaisons.

Csharp.svg
// 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 paramètres de type valeur à une méthode

Passage de types valeur par valeur

Csharp.svg
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

Csharp.svg
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 paramètres de type référence à une méthode

Passage de types référence par valeur

Csharp.svg
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

Csharp.svg
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 };
}