Question

Je suis la conception d'une langue, et je me demande s'il est raisonnable de types de référence non annulable par défaut et utiliser « ? » pour la valeur nullables et types référence. Y a-t-il des problèmes avec cela? Que feriez-vous à ce sujet:

class Foo {
    Bar? b;
    Bar b2;
    Foo() {
        b.DoSomething(); //valid, but will cause exception
        b2.DoSomething(); //?
    }
}
Était-ce utile?

La solution

Mon philosophie actuelle de la conception du langage est que la nullabilité devrait être quelque chose d'un programmeur est forcé de demander, non donné par défaut sur les types de référence (dans ce domaine, je suis d'accord avec Tony Hoare - Google pour son discours récent QCon).

Sur cet exemple spécifique, avec le unnullable b2, il ne respecterait même pas les contrôles statiques:. Analyse conservateur ne peut garantir que b2 est NULL, de sorte que le programme ne soit pas sémantiquement significative

Mon éthique est assez simple. Les références sont une poignée de indirection à une ressource, que nous pouvons traverser pour obtenir l'accès à cette ressource. les références sont nullables soit une poignée de indirection à une ressource, ou une notification que la ressource n'est pas disponible, et on est jamais sûr à l'avant qui sémantique sont utilisés. Cela donne soit une multitude de contrôles à l'avant (est-il nul? Non? Yay!), Ou l'inévitable NPE (ou équivalent). La plupart des ressources de programmation sont, ces jours-ci, et non des ressources limitées massivement ou lié à un modèle sous-jacent fini - références sont nulles, simplistes, l'un des ...

  • Paresse: « Je vais juste une valeur nulle dans bonde ici ». Ce qui franchement, je n'ai pas trop de sympathie avec
  • Confusion: « Je ne sais pas quoi mettre ici encore ». En règle générale aussi un héritage des langues anciennes, où vous deviez déclarer vos noms de ressources avant que vous saviez ce que vos ressources étaient.
  • Erreurs: "Il a mal tourné, voici un NULL". De meilleurs mécanismes de rapports d'erreur sont donc essentielles dans une langue
  • Un trou: « Je sais que j'aurai bientôt quelque chose, donnez-moi un espace réservé ». Cela a plus de mérite, et nous pouvons penser à des façons de lutter contre cela.

Bien sûr, la résolution de chacun des cas que NULL Caters en cours pour un choix meilleur linguistique est un exploit, et peut ajouter plus de confusion que cela aide. Nous pouvons toujours aller à des ressources immuables, alors NULL dans c'est que des états utiles (erreur et trou) n'est pas très réel. Impératif technqiues sont là pour rester bien, et je suis franchement heureux - ce qui rend la recherche de meilleures solutions dans cet espace utile

.

Autres conseils

types de référence Avoir être non nulle par défaut est le seul choix raisonnable. Nous sommes en proie à des langues et runtimes qui ont cette place à vis; vous devez faire la bonne chose.

Cette fonction était Spec # . Ils nullable références par défaut à et utilisé! pour indiquer non nullables. En effet, ils voulaient rétrocompatibilité.

Dans ma langue de rêve (dont je serais probablement le seul utilisateur!) Je fais comme vous, non annulable le même choix par défaut.

Je voudrais aussi rendre illégal d'utiliser le. opérateur sur une référence annulable (ou toute autre chose qui serait déréférencer). Comment qualifieriez-vous les utiliser? Il faudrait les convertir en non-nullables premier. Comment ferais-tu ceci? En les testant la valeur NULL.

En Java et C #, la déclaration de if ne peut accepter une expression de test bool. Je tiens à accepter le nom d'une variable de référence annulable:

if (myObj)
{
    // in this scope, myObj is non-nullable, so can be used
}

Cette syntaxe spéciale serait sans surprise aux programmeurs de C / C. Je préfère une syntaxe particulière comme celui-ci pour qu'il soit clair que nous faisons un contrôle qui modifie le type du nom myObj au sein de la branche de la vérité.

Je rajouterais un autre peu de sucre:

if (SomeMethodReturningANullable() into anotherObj)
{
    // anotherObj is non-nullable, so can be used
}

Cela donne juste le nom anotherObj au résultat de l'expression à gauche du into, de sorte qu'il peut être utilisé dans le cadre où elle est valide.

Je ferais le même genre de chose pour l'opérateur ?:.

string message = GetMessage() into m ? m : "No message available"; 

Notez que string message est non annulable, mais ce sont les deux résultats possibles du test ci-dessus, de sorte que l'affectation est la valeur.

Et alors peut-être un peu de sucre pour le cas vraisemblablement commun de substituer une valeur nulle:

string message = GetMessage() or "No message available";

Il est évident que or ne serait valablement appliqué à un type Nullable sur le côté gauche, et sur le côté droit non annulable.

(Je voudrais aussi avoir une intégré notion de propriété des champs d'instance;. Le compilateur générerait la méthode IDisposable.Dispose automatiquement, et la syntaxe ~Destructor serait utilisée pour augmenter Dispose, exactement comme en C ++ / CLI)

Spec # avait une autre extension syntaxique liés à la non-nullables, en raison du problème de veiller à ce que les non-nullables avait été initialisé correctement lors de la construction:

class SpecSharpExampleClass
{
    private string! _nonNullableExampleField;

    public SpecSharpExampleClass(string s)
        : _nonNullableExampleField(s) 
    {

    }
}

En d'autres termes, vous devez initialiser les champs de la même manière que vous souhaitez appeler d'autres constructeurs avec base ou this -. À moins bien sûr que vous les initialisez directement à côté de la déclaration de champ

Jetez un oeil à la opérateur Elvis proposition de Java 7. Cela fait quelque chose de similaire, en ce qu'elle encapsule un chèque nul et l'expédition de la méthode dans un opérateur, avec une valeur de retour spécifiée si l'objet est nul. Par conséquent:

String s = mayBeNull?.toString() ?: "null";

vérifie si la chaîne est nulle s, et renvoie la chaîne « null » le cas échéant, et la valeur de la chaîne sinon. Nourriture pour la pensée, peut-être.

Quelques exemples de caractéristiques similaires dans d'autres langues:

Il y a aussi Nullable<T> (de C #), mais ce n'est pas un bon exemple en raison du traitement différent de référence par rapport à des types de valeurs.

Dans votre exemple, vous pouvez ajouter un opérateur message d'envoi conditionnel, par exemple.

b?->DoSomething();

Pour envoyer un message à b que si elle est non nulle.

Avoir la valeur NULL soit un paramètre de configuration, exécutoire dans la source des auteurs de code . De cette façon, vous permettra aux gens qui aiment les objets par défaut nullables les apprécier dans leur code source, tout en permettant à ceux qui voudraient tous leurs objets soient non nulle par défaut ont exactement cela. De plus, fournir des mots clés ou d'autres installations pour marquer explicitement que vos déclarations d'objets et types peuvent être annulable et qui ne peut pas, avec quelque chose comme nullable et not-nullable, pour remplacer les valeurs par défaut globales.

Par exemple

/// "translation unit 1"

#set nullable
{ /// Scope of default override, making all declarations within the scope nullable implicitly
     Bar bar; /// Can be null
     non-null Foo foo; /// Overriden, cannot be null
     nullable FooBar foobar; /// Overriden, can be null, even without the scope definition above 
}

/// Same style for opposite

/// ...

/// Top-bottom, until reset by scoped-setting or simply reset to another value
#set nullable;

/// Nullable types implicitly

#clear nullable;

/// Can also use '#set nullable = false' or '#set not-nullable = true'. Ugly, but human mind is a very original, mhm, thing.

Beaucoup de gens affirment que donner à chacun ce qu'ils veulent est impossible, mais si vous concevez une nouvelle langue, essayer de nouvelles choses. Tony Hoare a introduit le concept de null en 1965 parce qu'il ne pouvait pas résister à (ses propres mots), et nous payons pour cela depuis (aussi, ses propres mots, l'homme est regrettable de celui-ci). Point est, des gens intelligents, expérimentés font des erreurs qui coûtent le reste d'entre nous, ne prenez pas anyones des conseils sur cette page comme si elle était la seule vérité, y compris la mienne. Évaluer et penser.

J'ai lu beaucoup de nombreux coups de gueule sur la façon dont il nous est pauvres programmeurs inexpérimentés qui ne comprennent pas vraiment où vraiment utiliser null et où non, nous montrant des motifs et qui sont destinés les anti pour éviter de se tirer dans le pied. Pendant ce temps, des millions de programmeurs inexpérimentés encore produire plus de code dans les langues qui permettent null. I peut être inexpérimenté, mais je sais que mes objets ne bénéficient pas d'être annulable.

Je pense que les valeurs nulles sont bons: Ils sont une indication claire que vous avez fait quelque chose de mal. Si vous ne parvenez pas à initialiser quelque part une référence, vous obtenez un avis immédiat.

L'alternative serait que les valeurs sont parfois initialisées à une valeur par défaut. Les erreurs logiques sont alors beaucoup plus difficile à détecter, à moins que vous mettez la logique de détection dans les valeurs par défaut. Ce serait la même chose que simplement obtenir une exception de pointeur NULL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top