2017-10-20 3 views
-4

J'ai deux classes:Confondre à propos baissés dans C#

public class Asset { } 

public class Stock : Asset 
{ 
    ... 
} 

Quand j'écris:

Stock m = new Stock(); 
Asset а = m;    
Stock s = (Stock) а; 

Tout fonctionne très bien!

Mais quand j'écris ainsi:

Asset а = new Asset();    
Stock s = (Stock) а; 

résultat est InvalidCastException, pourquoi?

+1

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/ – Bmo

+1

Je ne suis pas un gourou C#, mais il semble que vous ayez une faute de frappe sur votre second exemple: "Asset a = new Assert();" Il y a un "r" supplémentaire dans votre Asset. – bakoyaro

+0

Pourquoi Asset est-il même concret en premier lieu? Sûrement cela devrait être abstrait. –

Répondre

1

Un stock est un atout. Un actif n'est pas un stock.

Supposons que vous ayez 3 méthodes dans votre classe de base d'actifs. Ceux-ci sont également présents en stock. Par conséquent, lorsque vous lancez un stock sur un actif, vous mettez en fait une restriction sur le stock. Votre objet, qui est un stock, est dit être un actif. Ce qu'il sait faire, car est un atout.

Le stock peut comporter 3 méthodes qui ne font pas partie de la classe d'actifs de base. Lorsque vous dites à un actif d'être un stock, il ne sait pas comment le faire, car il y a des parties de stock qui ne font pas partie de l'actif.

1

Dans votre première instance, a est une référence de type Asset, mais il est se référant à un objet dont le type réel d'exécution est Stock.

Stock m = new Stock(); 
Asset а = m;    
Stock s = (Stock) а; 

m, a et s sont toutes différentes références au même objet réel, dont le type est Stock.

Ici, l'objet réel pas un Stock. Il est juste un Asset:

Asset а = new Assert();    
Stock s = (Stock) а; 

Parce qu'un Stock hérite de Asset, il est un surensemble de Asset. Vous pouvez prétendre qu'un Stock est un Asset et c'est très bien, car Stockest, en partie, un Asset - plus tout ce qu'il ajoute seul. Naturellement, cela ne coupe pas les deux sens: Un Asset n'a pas toutes les choses Stock a, donc vous ne pouvez pas le traiter comme s'il s'agissait d'un Stock.

Votre affectation à a dans le premier exemple n'a pas changé l'objet dans un Asset, ou créer une nouvelle Asset et l'affecter à m. C'était toujours le même objet.

Le type de la référence n'est qu'une partie de l'histoire.

Essayez ceci:

Stock m = new Stock(); 
Asset а = m;    

// This will print "Stock" -- it's still that same actual Stock object. 
Console.WriteLine(a.GetType()); 

Stock s = (Stock) а; 

Les classes sont "types de référence". Ils existent sur "le tas", dans l'obscurité quelque part, et vous ne manipulez que des références à eux. Les entiers et les doubles sont différents.Ce sont des "types de valeur":

int n = 4; 
double d = (double)n; 

Ce code crée en fait un nouveau double, égal à 4.0. d ne "fait pas référence à" n; c'est la sienne, une valeur différente. C'est très différent du fonctionnement des types de référence.

Ce truc est une caractéristique fondamentale du système de type .NET. Un struct (par exemple DateTime) est également un type de valeur.