Dois-je utiliser int ou Int32


352

En C #, intet Int32c'est la même chose, mais j'ai lu un certain nombre de fois ce qui intest préféré Int32à aucune raison donnée. Y a-t-il une raison et dois-je m'en soucier?


Tweetez par le Skeet à ce sujet où il privilégie Int32 sur int lors de la programmation des API.
comecme

@JohnBubriski: et ne l' oublions pas qu'il nécessite moins en utilisant des instructions pour l' utiliser (ou vous seriez taper System.Int32)
sehe

J'ai une question: nous n'utilisons pas directement le type CLR mais pourquoi en avons-nous besoin ??
AminM

La mise à jour du statut Facebook @JohnBubriski est plus facile à taper qu'un morceau de code. Mauvaise pensée là-bas! Plus facile à lire et à comprendre est beaucoup plus important que plus facile à taper. When something can be read without effort, great effort has gone into its writing. Easy writing is hard reading
7hi4g0

Réponses:


134

ECMA-334 : 2006 Spécification du langage C # (p18):

Chacun des types prédéfinis est un raccourci pour un type fourni par le système. Par exemple, le mot clé intfait référence à la structure System.Int32. Pour des raisons de style, l'utilisation du mot-clé est préférée à l'utilisation du nom complet du type de système.


271

Les deux sont en effet synonymes; intsera un peu plus familier, Int32rend les 32 bits plus explicites pour ceux qui lisent votre code. Je serais enclin à utiliser intoù j'ai juste besoin d'un `` entier '', Int32où la taille est importante (code cryptographique, structures) afin que les futurs responsables sachent qu'il est sûr d'agrandir un intsi approprié, mais je devrais prendre soin de changerInt32 s de la même manière.

Le code résultant sera identique: la différence est purement liée à la lisibilité ou à l'apparence du code.


65
Les personnes qui lisent votre code doivent savoir que int est un alias pour System.Int32. En ce qui concerne la lisibilité, la cohérence est beaucoup plus importante.
Troels Thomsen

11
Pour ceux d'entre vous avec l'ancien état d'esprit C ++, IntPtr est conçu pour être 32 bits sur un système d'exploitation 32 bits et 64 bits sur un système d'exploitation 64 bits. Ce comportement est spécifiquement mentionné dans sa balise de résumé. msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx
diadème

87

Ils déclarent tous deux des entiers 32 bits et, comme d'autres affiches l'ont indiqué, celui que vous utilisez est principalement une question de style syntaxique. Cependant, ils ne se comportent pas toujours de la même manière. Par exemple, le compilateur C # ne permet pas ceci:

public enum MyEnum : Int32
{
    member1 = 0
}

mais cela permettra:

public enum MyEnum : int
{
    member1 = 0
}

Allez comprendre.


9
Si vous utilisez Reflector pour examiner le type System.Int32, vous constaterez qu'il s'agit d'une structure et non d'une classe. Le code ressemble à ceci: [Serializable, StructLayout (LayoutKind.Sequential), ComVisible (true)] struct public Int32: IComparable, IFormattable, IConvertible, IComparable <int>, IEquatable <int> {public const int MaxValue = 0x7fffffff; ... Vous ne pouvez pas dériver un type d'une structure. À tout le moins, vous obtiendrez une erreur qui vous le dit. Cependant, le comportement d'énumération est un peu différent, que je commenterai ensuite.
raddevus

16
L'incapacité à dériver une énumération de l'Int32 est un comportement conçu, qui peut également être vu en regardant le code .NET: [Serializable, ComVisible (true)] public abstract class Enum: ValueType, IComparable, IFormattable, notez que Enum est dérivé de ValueType? Si vous essayez de dériver une énumération d'autre chose qu'un type de données intrinsèque (int, octet, etc.), vous recevrez une erreur qui ressemble à: Type octet, sbyte, court, ushort, int, uint, long ou ulong attendu .
raddevus

2
@daylight note que spécifier un enumà utiliser intn'est pas un derive, mais spécifier un underlying type; voir msdn.microsoft.com/en-us/library/sbbt4032.aspx#code-snippet-2
Jeroen Wiert Pluimers

2
@JeroenWiertPluimers Cependant, il est toujours intéressant de savoir pourquoi ils ont choisi de vérifier littéralement le type sous-jacent et de lancer CS1008 , car le type sous-jacent n'est que le type des constantes dans l'énumération, donc cela n'a pas vraiment d'importance lors de la compilation.
IllidanS4 veut que Monica revienne

5
@ IllidanS4, avec le nouveau compilateur Roslyn - cela a été corrigé, et les deux variantes valides
Grundy

49

J'utilise toujours les types de systèmes - par exemple, Int32au lieu de int. J'ai adopté cette pratique après avoir lu la programmation Applied .NET Framework - l'auteur Jeffrey Richter est un bon argument pour l'utilisation des noms de type complets. Voici les deux points qui m'ont marqué:

  1. Les noms de type peuvent varier entre les langages .NET. Par exemple, en C #, longmappe vers System.Int64 tandis qu'en C ++ avec des extensions gérées, longmappe vers Int32. Étant donné que les langues peuvent être mélangées et mises en correspondance lors de l'utilisation de .NET, vous pouvez être sûr que l'utilisation du nom de classe explicite sera toujours plus claire, quelle que soit la langue préférée du lecteur.

  2. De nombreuses méthodes de framework ont ​​des noms de type dans le cadre de leurs noms de méthode:

    BinaryReader br = new BinaryReader( /* ... */ );
    float val = br.ReadSingle();     // OK, but it looks a little odd...
    Single val = br.ReadSingle();    // OK, and is easier to read

Un problème avec cela est que la saisie semi-automatique de Visual Studio utilise toujours int. Donc, si vous faites un List<Tuple<Int32, Boolean>> test = new, Visual Studio va maintenant insérer List<Tuple<int, bool>>(). Connaissez-vous un moyen de modifier ces compléments automatiques?
MrFox

2
Oui, c'est un problème; non, je ne sais pas comment les changer tout de suite. Le point # 2 n'est plus un problème pour moi, car j'ai tendance à en utiliser varautant que possible pour réduire la verbosité du code. Dans les endroits occasionnels où la saisie semi-automatique entre et crache sur mon sol, je m'ajuste manuellement - c'est littéralement une seconde ou deux de mon temps.
Remi Despres-Smyth

20

int est un mot clé C # et n'est pas ambigu.

La plupart du temps, cela n'a pas d'importance, mais deux choses vont à l'encontre d'Int32:

  • Vous devez avoir un "système d'utilisation;" déclaration. l'utilisation de "int" ne nécessite aucune instruction using.
  • Il est possible de définir votre propre classe appelée Int32 (ce qui serait idiot et déroutant). int signifie toujours int.

Il est également possible de créer votre propre classe 'var', mais cela ne décourage pas les gens de l'utiliser.
Neme

Chaque mot clé est un mot clé C #. int était déjà utilisé en C et C ++. Il n'y a donc rien de spécifiquement C # à ce sujet.
MrFox

12

Comme déjà indiqué, int= Int32. Pour être sûr, assurez-vous de toujours utiliser int.MinValue/ int.MaxValuelors de l'implémentation de tout ce qui concerne les limites des types de données. Supposons que .NET ait décidé que ce intserait désormais le cas Int64, votre code serait moins dépendant des limites.


8
@spoulson: Erreur de commentaire sur la ligne 1: affectation interdite entre types égaux. Oui, une mauvaise blague.
Johann Gerell

22
Si la spécification C # (c'est un C #, pas de décision .NET) jamais décidé de changer pour faire int64 bits, ce serait comme un changement de rupture que je ne crois pas qu'il soit possible (ou certainement sensible) au code défensivement contre de telles éventualités.
Jon Skeet

9

La taille des octets pour les types n'est pas trop intéressante lorsque vous n'avez à gérer qu'une seule langue (et pour le code que vous n'avez pas à vous rappeler des débordements mathématiques). La partie qui devient intéressante est lorsque vous faites le pont entre une langue et une autre, un objet C # vers COM, etc., ou que vous effectuez un changement de bit ou un masquage et que vous devez vous rappeler (et à vos co-wokers de révision de code) de la taille des données.

Dans la pratique, j'utilise habituellement Int32 juste pour me rappeler de quelle taille ils sont parce que j'écris du C ++ managé (pour faire le pont vers C # par exemple) ainsi que du C ++ non managé / natif.

Tant que vous le savez probablement, en C # est de 64 bits, mais en C ++ natif, il se termine en 32 bits, ou char est unicode / 16 bits tandis qu'en C ++, il est de 8 bits. Mais comment savons-nous cela? La réponse est, parce que nous l'avons recherchée dans le manuel et elle l'a dit.

Avec le temps et les expériences, vous commencerez à être plus attentif aux types lorsque vous écrivez des codes pour faire le pont entre C # et d'autres langages (certains lecteurs ici pensent "pourquoi le feriez-vous?"), Mais à mon humble avis, c'est une meilleure pratique parce que Je ne me souviens pas de ce que j'ai codé la semaine dernière (ou je n'ai pas besoin de spécifier dans mon document API que "ce paramètre est un entier 32 bits").

En F # (même si je ne l'ai jamais utilisé), ils définissent int , int32 et nativeint . La même question devrait se poser, "laquelle dois-je utiliser?". Comme d'autres l'ont mentionné, dans la plupart des cas, cela ne devrait pas avoir d'importance (devrait être transparent). Mais pour ma part, je choisirais int32 et uint32 juste pour supprimer les ambiguïtés.

Je suppose que cela dépendrait simplement des applications que vous codez, de qui l'utilise, des pratiques de codage que vous et votre équipe suivez, etc. pour justifier quand utiliser Int32.


Cela n'invalide-t-il pas le but de .net? Qu'est-ce que F # de toute façon, une idée que Gates a eue avec sa retraite ...
Nick Turner

8

Il n'y a pas de différence entre intet Int32, mais comme intc'est un mot-clé de langue, beaucoup de gens le préfèrent stylistiquement (comme avec stringvs String).


7

D'après mon expérience, cela a été une convention. Je ne connais aucune raison technique d'utiliser int sur Int32, mais c'est:

  1. Plus rapide à taper.
  2. Plus familier au développeur C # typique.
  3. Une couleur différente dans la mise en évidence de la syntaxe Visual Studio par défaut.

J'aime particulièrement ce dernier. :)


7

J'utilise toujours les types alias (int, chaîne, etc.) lors de la définition d'une variable et utilise le vrai nom lors de l'accès à une méthode statique:

int x, y;
...
String.Format ("{0}x{1}", x, y);

Il semble juste moche de voir quelque chose comme int.TryParse (). Il n'y a pas d'autre raison que le style.


5

Je sais que la meilleure pratique consiste à utiliser int, et tout le code MSDN utilise int. Cependant, il n'y a pas de raison autre que la normalisation et la cohérence à ma connaissance.


5

Bien qu'ils soient (pour la plupart) identiques (voir ci-dessous pour la seule différence [bug]), vous devez certainement vous en soucier et vous devez utiliser Int32.

  • Le nom d'un entier 16 bits est Int16. Pour un entier 64 bits, c'est Int64, et pour un entier 32 bits, le choix intuitif est: int ou Int32?

  • La question de la taille d'une variable de type Int16, Int32 ou Int64 est auto-référencée, mais la question de la taille d'une variable de type int est une question parfaitement valide et les questions, aussi banales soient-elles, distraient, conduisent à la confusion, à la perte de temps, à la discussion, etc. (le fait que cette question existe prouve le fait).

  • L'utilisation d'Int32 permet au développeur de prendre conscience de son choix de type. Quelle est la taille d'un int? Oh ouais, 32. La probabilité que la taille du type soit réellement prise en compte est plus grande lorsque la taille est incluse dans le nom. L'utilisation d'Int32 favorise également la connaissance des autres choix. Quand les gens ne sont pas obligés de reconnaître au moins qu'il existe des alternatives, il devient beaucoup trop facile pour int de devenir "LE type entier".

  • La classe dans le cadre destinée à interagir avec des entiers 32 bits est nommée Int32. Encore une fois, ce qui est: plus intuitif, moins déroutant, il manque une traduction (inutile) (pas une traduction dans le système, mais dans l'esprit du développeur), etc. int lMax = Int32.MaxValueou Int32 lMax = Int32.MaxValue?

  • int n'est pas un mot-clé dans tous les langages .NET.

  • Bien qu'il existe des arguments pour lesquels il est peu probable qu'il change, int peut ne pas toujours être un Int32.

Les inconvénients sont deux caractères supplémentaires à taper et [bug].

Cela ne compilera pas

public enum MyEnum : Int32
{
    AEnum = 0
}

Mais cela:

public enum MyEnum : int
{
    AEnum = 0
}

Vous dites "Le nom d'un entier 16 bits est Int16, pour un entier 64 bits c'est Int64, et pour un entier 32 bits le choix intuitif est: int ou Int32?", Mais il existe également des mots clés C # pour ceux-ci. Int16 = court Int64 = long Donc, le premier point de votre réponse est basé sur une hypothèse incorrecte.
Mel

"La variable de type int est une question parfaitement valide et les questions, aussi banales soient-elles, distraient, conduisent à la confusion, perdent du temps, gênent la discussion, etc. (le fait que cette question existe prouve le fait)." Vous plaisantez j'espère? Vous travaillez dans un langage que vous ne comprenez pas complètement ce qui se cache derrière le capot. Si le développeur ne comprend pas ce que le type primitif équivaut à, il devrait se lancer dans les arts culinaires. Cela ressemble à un développeur VB. l'utilisation de primitives est native de n'importe quelle langue et doit être préférée. C'est bien si vous n'aimez pas les primitives, mais n'inventez pas les réalités.
Nick Turner

Hmm, je suis totalement en désaccord avec votre opinion selon laquelle je devrais m'en soucier ... mais je ne savais pas que les énumérations ne pouvaient hériter que des mots clés. Un fait assez inutile, mais toujours amusant à savoir :)
Jowen

4

Vous ne devriez pas vous en soucier. Vous devriez utiliser la intplupart du temps. Cela aidera le portage de votre programme vers une architecture plus large à l'avenir (c'est actuellement intun alias System.Int32mais cela pourrait changer). Ce n'est que lorsque la largeur de bits de la variable importe (par exemple: pour contrôler la disposition en mémoire de a struct) que vous devez utiliser int32et d'autres (avec le " using System;" associé ).


1
Vous ne pouvez pas être sérieux ... rendre le portage plus facile? Je ne pense pas que trouver et remplacer soit un gros problème.
Vince Panuccio

2
(actuellement int est un alias de System.Int32 mais cela pourrait changer) ? Oh viens un ... Êtes-vous sérieux?
Oybek

Pourquoi voudriez-vous écrire du code dans un langage que vous souhaitez éventuellement supprimer? On dirait que par décision de gestion. Utilisez int ou Int32. Int32 ressemble à VB
Nick Turner

Ce que je voulais dire, c'est que MAYBE, (et c'est un gros MAYBE, je ne sais pas vraiment pourquoi les concepteurs l'ont fait de cette façon), vous devriez avoir un moyen de déclarer un int qui a la même largeur que l'arche sur laquelle vous courez, comme les œuvres int / long / ... de C. Il s'agit d'un mécanisme (int vers alias int32) qui semble conçu pour faire exactement cela. Et prenez en considération Microsoft recommande toujours d'utiliser "int" vs "Int32" (tout comme ils le feraient si c'était leur intention initiale). Je sais, c'est un gros IF ... Quand j'ai écrit cette réponse, il n'y avait pas de framework .NET 64 bits, donc je ne savais pas ce qu'ils feraient dans ce cas.
Yanko Hernández Alvarez

3

int est le raccourci du langage C # pour System.Int32

Bien que cela signifie que Microsoft pourrait modifier ce mappage, un post sur les discussions de FogCreek a déclaré [source]

"Sur le problème 64 bits - Microsoft travaille en effet sur une version 64 bits du .NET Framework mais je suis quasiment sûr que le mappage ne sera PAS sur 64 bits sur ce système.

Les raisons:

1. La norme C # ECMA dit spécifiquement que int est 32 bits et long est 64 bits.

2. Microsoft a introduit des propriétés et méthodes supplémentaires dans Framework version 1.1 qui renvoient des valeurs longues au lieu de valeurs int, telles que Array.GetLongLength en plus d'Array.GetLength.

Je pense donc qu'il est prudent de dire que tous les types C # intégrés conserveront leur mappage actuel. "


Si une version 64 bits est introduite, ils ajouteront probablement 'nativeint' à C # (tel qu'il est actuellement utilisé en F #). Cela renforce simplement le fait que l'introduction de «int» et sa définition en tant qu'Int32 était une erreur! Et donc incohérent d'un point de vue API (c'est-à-dire ReadInt32 pas ReadInt), couleur (foncé vs bleu clair) et sensibilité à la casse (DateTime vs int). c'est-à-dire pourquoi le type de valeur 'DateTime' n'a pas d'alias comme Int32?
Carlo Bos

3

int est le même que System.Int32 et une fois compilé, il se transformera en la même chose en CIL .

Nous utilisons int par convention en C # car C # veut ressembler à C et C ++ (et Java) et c'est ce que nous utilisons là-bas ...

BTW, je finis par utiliser System.Int32 lors de la déclaration des importations de diverses fonctions de l'API Windows. Je ne sais pas si c'est une convention définie ou non, mais cela me rappelle que je vais sur une DLL externe ...


3

Il était une fois, le type de données int était lié à la taille de registre de la machine ciblée par le compilateur. Ainsi, par exemple, un compilateur pour un système 16 bits utiliserait un entier 16 bits.

Cependant, heureusement, nous ne voyons plus beaucoup de 16 bits, et lorsque le 64 bits a commencé à devenir populaire, les gens étaient plus soucieux de le rendre compatible avec les anciens logiciels et le 32 bits existait depuis si longtemps que pour la plupart des compilateurs, un int est simplement supposé être de 32 bits.


3

Je recommanderais d'utiliser StyleCop de Microsoft .

C'est comme FxCop , mais pour des problèmes liés au style. La configuration par défaut correspond aux guides de style internes de Microsoft, mais elle peut être personnalisée pour votre projet.

Cela peut prendre un peu de temps pour s'y habituer, mais cela rend certainement votre code plus agréable.

Vous pouvez l'inclure dans votre processus de génération pour vérifier automatiquement les violations.


Je suis complètement en désaccord avec StyleCop sur celui-ci. oui c'est bon mais je préfère utiliser Int32, pourquoi? pour éviter des réponses comme les deux votes négatifs. Les gens confondent Int32 avec la façon dont les ints sont représentés dans C
John Demetriou

2

intet Int32c'est pareil. intest un alias pour Int32.


int n'est pas un alias, c'est un mot-clé. Voir les autres réponses.
Timores du

int est certainement un mot-clé pour la langue mais il peut aussi être appelé un alias de System.Int32. De plus, une autre façon de penser est que vous avez une using int = System.Int32; directive pour tous vos fichiers de code source.
uygar donduran

2

Vous ne devriez pas vous en soucier. Si la taille est un problème, j'utiliserais octet, court, entier, puis long. La seule raison pour laquelle vous utiliseriez un int supérieur à int32 est si vous avez besoin d'un nombre supérieur à 2147483647 ou inférieur à -2147483648.

A part ça, je m'en fous, il y a plein d'autres choses à se soucier.


J'ajouterais que vous pouvez utiliser le mot clé "long" au lieu de System.Int64
Keith

22
Vous avez mal compris la question. L'OP demande s'il y a une différence entre les déclarations "int i" et "Int32 i".
corbeau

2

Cela ne fait aucune différence dans la pratique et avec le temps, vous adopterez votre propre convention. J'ai tendance à utiliser le mot clé lors de l'attribution d'un type et la version de la classe lors de l'utilisation de méthodes statiques et autres:

int total = Int32.Parse("1009");


1

J'utilise int dans le cas où Microsoft modifie l'implémentation par défaut d'un entier en une nouvelle version fangled (appelons-la Int32b).

Microsoft peut alors changer l'alias int en Int32b, et je n'ai pas besoin de changer mon code pour profiter de leur nouvelle implémentation entière (et, espérons-le, améliorée).

Il en va de même pour tous les mots-clés de type.


0

Vous ne devriez pas vous soucier de la plupart des langages de programmation, sauf si vous avez besoin d'écrire des fonctions mathématiques très spécifiques ou du code optimisé pour une architecture spécifique ... Assurez-vous simplement que la taille du type vous suffit (utilisez quelque chose de plus grand qu'un Int si vous sachez que vous aurez besoin de plus de 32 bits par exemple)


0

Ça n'a pas d'importance. int est le mot-clé de la langue et Int32 son type de système réel.

Voir aussi ma réponse ici à une question connexe.


0

L'utilisation d'Int ou d'Int32 est la même Int est juste du sucre pour simplifier le code pour le lecteur.

Utilisez la variante Nullable Int? ou Int32? lorsque vous travaillez avec des bases de données sur des champs contenant null. Cela vous évitera de nombreux problèmes d'exécution.


0

Certains compilateurs ont des tailles différentes pour int sur différentes plates-formes (non spécifiques à C #)

Certaines normes de codage (MISRA C) exigent que tous les types utilisés soient de taille spécifiée (c'est-à-dire Int32 et non int).

Il est également bon de spécifier des préfixes pour différentes variables de type (par exemple b pour octet 8 bits, w pour mot 16 bits et l pour mot long 32 bits => Int32 lMyVariable)

Vous devriez vous en soucier car cela rend votre code plus portable et plus facile à gérer.

Portable peut ne pas être applicable à C # si vous allez toujours utiliser C # et la spécification C # ne changera jamais à cet égard.

L'ihmo maintenable sera toujours applicable, car la personne qui gère votre code peut ne pas être au courant de cette spécification C # particulière, et manquer un bogue si l'int devient parfois plus de 2147483647.

Dans une simple boucle for qui compte par exemple les mois de l'année, vous ne vous en souciez pas, mais lorsque vous utilisez la variable dans un contexte où elle pourrait éventuellement s'écouler, vous devriez vous en soucier.

Vous devriez également vous soucier si vous allez faire des opérations au niveau du bit.


Cela ne fait aucune différence dans .Net - int est toujours Int32 et long est toujours Int64
Keith

It is also good to specify prefixes for different type variablesLa notation hongroise est aujourd'hui largement déconseillée et la plupart des styles de codage découragent son utilisation. Les conventions internes des
éditeurs

0

L'utilisation du Int32type nécessite une référence à l'espace de noms Systemou une qualification complète ( System.Int32). J'ai tendance à le faire int, car il ne nécessite pas d'importation d'espace de noms, ce qui réduit les risques de collision d'espace de noms dans certains cas. Lorsqu'il est compilé en IL, il n'y a aucune différence entre les deux.


0

Selon la fenêtre immédiate dans Visual Studio 2012, Int32 est int, Int64 est long. Voici la sortie:

sizeof(int)
4
sizeof(Int32)
4
sizeof(Int64)
8
Int32
int
    base {System.ValueType}: System.ValueType
    MaxValue: 2147483647
    MinValue: -2147483648
Int64
long
    base {System.ValueType}: System.ValueType
    MaxValue: 9223372036854775807
    MinValue: -9223372036854775808
int
int
    base {System.ValueType}: System.ValueType
    MaxValue: 2147483647
    MinValue: -2147483648

0

Pensez également à Int16. Si vous avez besoin de stocker un nombre entier en mémoire dans votre application et que vous êtes préoccupé par la quantité de mémoire utilisée, vous pouvez opter pour Int16 car il utilise moins de mémoire et a une plage min / max plus petite que Int32 (qui est ce que int est .)


0

Il y a quelque temps, je travaillais sur un projet avec Microsoft lorsque nous avons eu la visite d'un membre de l'équipe produit Microsoft .NET CLR. Cette personne a codé des exemples et lorsqu'il a défini ses variables, il a utilisé «Int32» vs «int» et «String» vs «string».

Je me souvenais avoir vu ce style dans un autre exemple de code de Microsoft. J'ai donc fait quelques recherches et j'ai découvert que tout le monde dit qu'il n'y a pas de différence entre «Int32» et «int» à l'exception de la coloration syntaxique. En fait, j'ai trouvé beaucoup de matériel suggérant que vous utilisiez "Int32" pour rendre votre code plus lisible. J'ai donc adopté le style.

L'autre jour, j'ai trouvé une différence! Le compilateur ne vous permet pas de taper enum en utilisant «Int32», mais il le fait lorsque vous utilisez «int». Ne me demandez pas pourquoi parce que je ne sais pas encore.

Exemple:

public  enum MyEnum : Int32
{
    AEnum = 0
}

Cela marche.

public enum MyEnum : int
{
    AEnum = 0
}

Extrait de: notation Int32 vs int

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.