2008-10-25 5 views
50

ceci est une question que lorsque je programmation me demande toujours: Que utiliser quand nous l'écriture de code:Que utiliser: var ou type de nom d'objet?

var myFiles = Directory.GetFiles(fullPath); 

ou

string[] myFiles = Directory.GetFiles(fullPath); 

var est nouveau et est un Implicitement dactylographié Variables locales, donc nous ne pouvons utiliser que localement et il a des règles comme ne peut pas être nul, etc., mais je me demande si nous avons l'avantage de l'utiliser "normalement".

La partie dit « normalement », pas Types anonymes, objet et Collection Initialiseur et expressions de requête où c'était l'intention d'utiliser le var objet anonyme, donc ce que je veux dire est ... juste comme l'exemple ci-dessus.

que pensez-vous?

+2

Bonne question. – Contango

Répondre

59

Au-delà de l'utilisation évidente de var avec LINQ, je l'utilise aussi pour abréger les déclarations de variables poilues pour une meilleure lisibilité, par exemple:

var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>(); 

En général, je reçois une sorte de confort (faute d'un meilleur mot) de typage statique qui me fait hésiter à l'abandonner. J'aime le sentiment que je sais ce que je fais quand je déclare une variable. Déclarer une variable n'est pas seulement dire quelque chose au compilateur, c'est dire à la personne qui lit votre code quelque chose. Laissez-moi vous donner un exemple.

Supposons que j'ai une méthode qui renvoie un List<string>. Ce code est certainement correct, et je pense qu'il est ainsi 90% des développeurs C# serait probablement écrire:

List<string> list = MyMethod(); 

De toute évidence, non? En fait, voici un endroit où vous pourriez tout aussi facilement utiliser var.

Assez vrai. Mais cette version du code est non seulement déclaration d'une variable, il me dit ce que la personne qui l'a écrit l'intention de faire:

IEnumerable<string> list = MyMethod(); 

Le développeur qui a écrit que le code me dit: « Je suis Je ne vais pas changer cette liste, je ne vais pas non plus utiliser un index pour accéder à ses membres, tout ce que je vais faire c'est de le parcourir. C'est beaucoup d'informations à transmettre dans une seule ligne de code. C'est quelque chose que vous abandonnez si vous utilisez var.

Bien sûr, vous n'abandonnez pas si vous ne l'utilisiez pas en premier lieu. Si vous êtes le genre de développeur qui écrirait cette ligne de code, vous savez déjà que vous n'utiliserez pas var là.

Edit:

Je viens de relire le poste de Jon Skeet, et cette citation d'Eric Lippert m'a sauté aux yeux:

habitants Implicitement typés ne sont qu'une petite façon dont vous pouvez deemphasize la comment et ainsi mettre l'accent sur le quoi.

Je pense que dans beaucoup de cas, en utilisant la typage implicite, on laisse ce qui est implicite. C'est juste de ne pas s'attarder sur le quoi. Par exemple, je vais avec désinvolture écrire une requête LINQ comme:

var rows = from DataRow r in parentRow.GetChildRows(myRelation) 
      where r.Field<bool>("Flag") 
      orderby r.Field<int>("SortKey") 
      select r; 

Quand je lis ce code, l'une des choses que je pense quand je suis en train de lire, il est "rows est un IEnumerable<DataRow>.«Parce que je sais que ce que LINQ requêtes retour est IEnumerable<T>, et je peux voir le type de l'objet sélectionné là.

C'est un cas où la ce n'a pas été explicité. Il a été laissé pour moi .. pour en déduire

maintenant, dans environ 90% des cas où j'utiliser LINQ, cela n'a pas d'importance un petit peu parce que 90% du temps, la ligne de code suivante est:

foreach (DataRow r in rows) 

Mais il n'est pas difficile d'imaginer un code dans lequel il serait très utile de déclarer rows comme IEnumerable<DataRow> - code où de nombreux types d'objets différents étaient interrogés, il n'était pas possible de placer la déclaration de requête à côté de l'itération, et il serait utile de pouvoir inspecter rows avec IntelliSense. Et c'est une chose, pas une chose.

+3

Pour le dernier bit, je ne suis pas d'accord. Le "quoi" ne signifie pas "de quel type il s'agit", mais "à quoi sert-il". Je sais que "var rows" déclare une variable contenant mes lignes. Que dois-je savoir de plus? Vraisemblablement, il se comporte comme une collection de lignes, donc je ne me soucie pas vraiment du type précis. – jalf

+0

Je vois dans l'énorme base de code chez les développeurs de mon entreprise en utilisant cela pour enregistrer quelques frappes et déplacer un fardeau de compréhension pour le lecteur.Je ne doute pas que quiconque utilise cette réponse peut rendre le code plus lisible - s'il donne un sacré bonhomme et utilise un bon jugement - mais dans le monde réel, les développeurs paresseux ont du bon temps avec ça. – toddmo

+0

Je voulais juste souligner que vous n'avez pas besoin d'abandonner la saisie statique lorsque vous utilisez 'var'. Ce sont des concepts mutuellement exclusifs. L'accès rapide pour les futurs visiteurs ... ** Typage statique vs dynamique **: * Statique * vérifie à la compilation alors que * Dynamique * vérifie à l'exécution. ** Typage explicite ou implicite **: * La déclaration de variable explicite * inclut le type épelé tandis que * La déclaration de variable implicite * signifie que le compilateur déduit le type correct. – KyleMit

41

Vous obtiendrez une grande variété d'opinions sur celui-ci - de "utiliser var partout" à "utiliser uniquement var avec des types anonymes, où vous devez essentiellement." J'aime Eric Lippert's take on it:

Tout le code est une abstraction. Est-ce que le code «fait vraiment» est en manipulant des données? Numéros? Morceaux? N ° Voltages? Non, les électrons? Oui, mais comprendre le code au niveau de est une mauvaise idée! L'art du codage consiste à déterminer quel est le bon niveau d'abstraction pour l'audience .

Dans un langage de haut niveau, il est toujours cette tension entre ce que le code fait (sémantiquement) et comment le code accomplit. Maintenance les programmeurs doivent comprendre à la fois le quoi et le comment s'ils vont pour réussir à faire des changements.

Tout le point de LINQ est que désactive massivement le "comment" et souligne massivement le "quoi". En l'aide d'une compréhension de la requête, le programmeur dit à l'avenir public « Je crois que vous devriez ne prendra pas exactement comment cet ensemble de résultats est calculé, mais vous devriez prendre soin beaucoup sur ce que la sémantique de l'ensemble résultant sont. " Ils rapprochent le code du processus opérationnel mis en œuvre et plus loin des bits et des électrons qui le font aller.

habitants Implicitement tapés ne sont qu'un petit façon dont vous pouvez deemphasize comment et souligner ainsi le quoi. Que ce soit la bonne chose à faire dans un cas particulier est un appel de jugement .Donc, je dis aux gens que si la connaissance du type est pertinente et son choix est crucial pour le fonctionnement continu de la méthode, puis ne pas utiliser le typage implicite. Typage explicite dit "Je vous dis comment cela fonctionne pour une raison, payer attention". Le typage implicite dit "il n'importe pas un peu si cette chose est une liste ou un Client [], ce qui importe est que c'est une collection de clients."

Personnellement, je ne ont tendance à l'utiliser si le type n'est pas raisonnablement évidente - où j'inclure les requêtes LINQ comme étant « raisonnablement évidente ». Je ne le ferais pas pour Directory.GetFiles par exemple, car il n'est pas vraiment évident que cela renvoie un string[] au lieu de (disons) FileInfo[] (ou quelque chose d'autre entièrement) - et cela fait une grande différence pour ce que vous faites plus tard.

S'il y a un appel de constructeur sur le côté droit de l'opérateur d'affectation, je suis beaucoup plus susceptible d'aller avec var: il est flagrant de voir quel sera le type. Ceci est particulièrement pratique avec des types génériques complexes, par ex. Dictionary<string,List<int>>.

+3

Je le fais beaucoup pareil. Cependant, en plus de l'appel du constructeur sur le côté droit, je l'utilise toujours si le côté droit est lancé, c'est-à-dire qu'il y a un "comme MyType" à la fin. – OregonGhost

+3

"Electron Manipulator" sera désormais mon titre de fonction officiel: p – dvdvorle

11

Personnellement, je n'utilise que var en deux endroits:

  1. Avec des types anonymes, à savoir. liés LINQ (où var est nécessaire dans certains cas)
  2. Lorsque l'instruction déclare et construit un type spécifique au même type

ie. ceci est un exemple du point 2:

var names = new List<String>(); 

Edité: Ce en réponse à la question de Jon Skeet.

La réponse ci-dessus a été en fait simplifiée. Fondamentalement, j'utilise var où le type est soit:

  1. inutile de savoir (pas que beaucoup d'endroits bien)
  2. Impossible de savoir (LINQ, types anonymes)
  3. Autrement connu, ou clair de le code

Dans le cas d'une méthode d'usine, où tout ce que vous devez savoir à l'endroit où vous écrivez le code est que l'objet obtenu est un descendant d'un certain type, et que un certain type a une méthode d'usine statique, alors j'utiliserais var. Comme ceci:

var connection = DatabaseConnection.CreateFromConnectionString("..."); 

L'exemple ci-dessus est un exemple réel de mon code. Il est clair, au moins pour moi et les personnes qui utilisent ce code, que connexion est un descendant de DatabaseConnection, mais le type exact n'est pas nécessaire pour comprendre le code, ni l'utiliser.

+0

Qu'en est-il des méthodes d'usine statiques, par ex. Foo.CreateInstance (...)? –

+0

Pouvez-vous expliquer pourquoi définissez-vous: 'var connection = ...' si _ le type exact n'est pas nécessaire pour ne pas comprendre le code, ni pour l'utiliser._ –

+0

C'est juste un guide de style. –

9

J'ai essayé le style "use var everywhere" ... et voici pourquoi je n'ai pas continué à l'utiliser.

  1. lisibilité Dégradé parfois
  2. Limites IntelliSense après =
  3. Si vous tapez "var" était vraiment pas beaucoup plus courte que taper "int", "string", etc., en particulier avec IntelliSense.

Cela dit, je l'utilise toujours avec LINQ.

3

Cette post10 a quelques bonnes directives sur quand utiliser les types d'interface ou d'objet de type var.

1

Je pense qu'il est intéressant de noter comment cela est généralement géré dans Haskell. Grâce au Curry-Howard isomorphism, le type (le plus général) de toute expression dans Haskell peut être déduit, et donc les déclarations de type ne sont essentiellement requises nulle part, à quelques exceptions près; par exemple, parfois vous voulez délibérément limiter le type à quelque chose de plus spécifique que ce qui serait déduit.

Bien sûr, ce qui est requis et ce qui est recommandé ne sont pas la même chose; en pratique, la convention semble indiquer que les définitions de niveau supérieur ont toujours des déclarations de type, alors que les définitions localisées ont les déclarations de type omises. Cela semble trouver un bon équilibre entre l'explicite-pour-lisibilité de la définition dans son ensemble, contrastant avec la brièveté-pour-lisibilité des définitions locales «auxiliaires» ou «temporaires». Si je comprends bien, vous ne pouvez pas utiliser var pour les définitions de «niveau supérieur» (comme une méthode ou une fonction globale), donc je suppose que cela se traduit par «utiliser var partout où vous pouvez» dans C# monde. Bien sûr, en tapant "int" est le même nombre de touches que "var", mais la plupart des exemples seront plus long que cela.

3

Venant de la terre de la programmation fonctionnelle, où l'inférence de type règle le jour, j'utilise var pour tous les locaux autant que possible.

Dans Visual Studio, si vous vous demandez quel type de local existe, il vous suffit de le survoler avec votre souris.

3

J'ai tendance à utiliser var partout, mais mes collègues ont dit stop, il est moins lisible pour nous. Donc, maintenant, je n'utilise var que sur les types anonymes, les requêtes LINQ et où est le constructeur sur le côté droit.

Questions connexes