8
votes

Puis-je détecter si j'ai reçu un nouvel objet en tant que paramètre?

Version courte

Pour ceux qui n'ont pas le temps de lire mon raisonnement pour cette question ci-dessous: P>

Y a-t-il un moyen de faire respecter une politique de "nouveaux objets uniquement" ou "objets existants uniquement" pour les paramètres de la méthode forts>? p>

version longue h2>

Il existe de nombreuses méthodes qui prennent des objets comme des paramètres, et peu importe si le La méthode a l'objet "tout à lui-même" ou non. Par exemple: p> xxx pré>

ici la liste .ADD code> méthode a pris une "code" existant code> (Bob ) ainsi qu'une "nouvelle" personne code> (Larry), et la liste contient les deux éléments. Bob peut être consulté comme Bob code> ou [0] code>. Larry peut être accessible en tant que personnes [1] code> et, si désiré, mis en cache et accessible comme Larry code> (ou autre) par la suite. P>

OK, bien. Mais parfois, une méthode ne devrait pas em> être adoptée un nouvel objet. Prenons, par exemple, array.sort code>. Ce qui suit ne fait pas beaucoup de sens: P>

TryDoSomething(new StreamWriter(path));


7 commentaires

Très bonne question, je me demande si c'est un type de condition préalable pour la spécification # aussi.


Cela ressemble à la responsabilité du compilateur.


Je ne pense pas qu'il y ait une exigence pour cela, il peut être détecté au moment de la compilation et d'avertissement peut être élevé.


Ou compilateur peut-être déjà l'optimiser. Quand il détecte une telle déclaration


IMHO RE VOTRE EXEMPLE TEXTWRITEUR Vous le fermeriez où vous l'avez créé, alors trydosomething ne devrait pas faire cela. Je suppose que vous pourriez avoir un drapeau pour dire que comme un consommateur, il n'a plus besoin de la TW. Cela revient à l'architecture plutôt que des instances de paramètres.


C'est un peu la queue remue-t-elle cependant. Nous préférons ne pas transférer la propriété parce que c # n'a pas de moyen propre d'exprimer cela, plutôt que de transférer la propriété intrinsèquement mal.


En outre, il apparaît que le framework transfère parfois la propriété d'objets iDisopsables Stackoverflow.com/questions/674879/... , donc ce n'est pas quelque chose que vous pouvez toujours éviter


9 Réponses :


10
votes

non, fondamentalement.

Il n'y a vraiment aucune différence entre: xxx

et xxx

et parfois parfois Vous pouvez convertir entre les deux à des fins de débogage.

Notez que dans le datawow / Paramètre Exemple, il y a une approche alternative cependant - ce datarow peut < em> savez son parent dans le cadre de son état. Ce n'est pas la même chose que «nouveau» ou non - vous pourriez avoir une opération de «détacher» par exemple. Les conditions définies en termes de véritable état durement et rapide de l'objet rendent beaucoup plus de sens que les termes laineux tels que "nouveau".


1 commentaires

Selon les règles de l'étiquette d'objet d'Emily Postnet, un constructeur doit laisser un objet entièrement initialisé et prêt à être utilisé.



5
votes

non. Et s'il y a une raison quelconque que vous devez faire cela, votre code a une architecture inappropriée.


5 commentaires

Ne disant pas que Microsoft est parfait, mais son exemple est d'une méthode Microsoft qui bénéficierait d'une telle restriction / attribut: «OK, bien. Mais parfois, une méthode ne devrait vraiment pas être transmise d'un nouvel objet. Prenons, par exemple, Array. Trier . Ce qui suit ne fait pas beaucoup de sens: "Array.sort (nouveau int [] {5, 6, 3, 7, 2, 1});


Si cela ne fait pas beaucoup de sens, alors pourquoi écririez-vous ce code? Exactement.


Imaginez une seconde qu'une fonction est un lavage automatique de voiture. Devrait-il m'échapper juste parce que ma voiture est neuve et mousseuse propre? Bien sûr que non. Il a un travail à faire et ça s'en fiche.


Pourquoi ne puis-je pas trier un tableau temporaire?


@JOSH: Je ne dis pas nécessairement que ce que je demande, ce serait un bon choix de conception. Je me demandais principalement que si c'était possible. Cela dit, j'ai ajouté un exemple de méthode qui pourrait sembler avoir un peu plus de sens que array.sort (nouveau int [] {...}) - Bien que, vraiment, Je suppose que c'est aussi assez mal conçu. En fin de compte, je pense que je suis d'accord avec vous.



3
votes

Réponse courte - Non, il n'y a pas

dans la grande majorité des cas, je constate généralement que les problèmes que vous avez énumérés ci-dessus ne comptent pas vraiment tout cela. Lorsqu'ils vous permettent de surcharger une méthode pour pouvoir accepter autre chose en tant que paramètre au lieu de l'objet que vous êtes inquiet du partage. P>

// For example create a method that allows you to do this:
people.Add("Larry");

// Instead of this:
people.Add(new Person("Larry"));

// The new method might look a little like this:
public void Add(string name)
{
    Person person = new Person(name);
    this.add(person); // This method could be private if neccessary
}


0 commentaires

0
votes

Nope, il n'y a aucun moyen de savoir.

Tout ce qui est passé est la référence d'objet. Que ce soit «nouveau» in situ, ou provient d'une matrice, la méthode en question n'a aucun moyen de savoir comment les paramètres passés ont été instanciés et / ou où.


0 commentaires

6
votes

oui, il existe un moyen de le faire.

sorte de.

Si vous faites votre paramètre A Réf Paramètre, vous Je vais avoir une variable existante comme argument. Vous ne pouvez pas faire quelque chose comme ceci: xxx

si vous le faites, vous obtiendrez l'erreur "Un argument Ref ou Out doit être une variable assignable."

Bien sûr, en utilisant REF a d'autres implications. Cependant, si vous êtes celui qui écrit la méthode, vous n'avez pas besoin de vous inquiéter d'eux. Tant que vous ne réaffectez pas le paramètre Ref à l'intérieur de la méthode, cela ne fera aucune différence si vous utilisez une référence ou non.

Je ne dis pas que c'est un bon style, nécessairement. Vous ne devriez pas utiliser Ref ou Out, à moins que vous n'ayez vraiment pas besoin de et n'avez pas d'autre moyen de faire ce que vous faites. Mais utiliser REF fera ce que vous voulez faire du travail.


4 commentaires

J'apprécie vraiment que vous pensiez en dehors de la boîte et que vous avez proposé une idée qui fonctionnerait "en quelque sorte", bien que des inconvénients définis (comme vous admettez).


Si vous utilisez un paramètre Réf, l'appelant peut toujours passer à la fonction une variable contenant un objet créé juste avant d'appeler la fonction. De cette manière, vous n'avez pas résolu le problème de savoir si un objet a été créé juste avant l'appel à la fonction ou de beaucoup de temps avant cela; Vous avez simplement forcé les développeurs à ne pas utiliser d'appel comme dosomething (nouveau client ()), ce qui est parfois utilisé lorsque le paramètre transmis n'est utilisé que comme paramètre pour la fonction.


Le temps entre la création et l'utilisation n'est pas vraiment relavant ici, si je comprends le problème, il distingue davantage entre Lvalus et Rivalues ​​et quef semble garantir un lvalue. Il semble y avoir aucun moyen de garantir une r devale?


Kiamlaluno, tout ce que vous avez dit est correct. Mais ce que vous avez dit a peu à voir avec ce que Dan demandait.



0
votes

En tant que solution partielle possible si vous ne vouliez que l'un des objets consommés par une méthode, vous pourriez peut-être regarder un singleton. De cette manière, la méthode en question n'a pas pu créer un autre exemple s'il existait déjà.


0 commentaires

0
votes

Un moyen de savoir si un objet transmis à une fonction (ou une méthode) a été créé juste avant que l'appel à la fonction / méthode est que l'objet a une propriété initialisée avec l'horodatage transmis à partir d'une fonction système; De cette manière, en regardant cette propriété, il serait possible de résoudre le problème.

Franchement, je n'utiliserais pas une telle méthode parce que

  • Je ne vois aucune raison pour laquelle le code doit maintenant si le paramètre transumé est un droit d'objet créé, ou s'il a été créé à un moment différent.
  • La méthode que je suggère dépend d'une fonction système que dans certains systèmes ne pouvait pas être présente, ou cela pourrait être moins fiable.
  • Avec les processeurs modernes, qui sont un moyen plus rapide que les processeurs utilisés il y a 10 ans, il pourrait y avoir le problème d'utiliser la bonne valeur pour la valeur seuil pour décider lors de la création d'un objet, ou non.

    L'autre solution consisterait à utiliser une propriété d'objet qui est définie sur une valeur de l'objet Créateur, et qui est définie sur une valeur différente de toutes les méthodes de l'objet.
    Dans ce cas, le problème serait d'oublier d'ajouter le code pour modifier cette propriété dans chaque méthode.

    Encore une fois, je me demanderais de me demander "est-il vraiment besoin de faire ça?".


0 commentaires

3
votes

Je peux penser à un moyen de faire cela, mais je ne le recommanderais certainement pas. Juste pour l'argumentation de l'argument.

Qu'est-ce que cela signifie pour qu'un objet soit un "nouveau" objet? Cela signifie qu'il n'y a qu'une seule référence la gardant en vie. Un objet "existant" aurait plus d'une référence à cela.

Dans cet esprit, regardez le code suivant: xxx

Ceci imprime true sur la première ligne, false sur la seconde. Mais encore une fois, veuillez ne pas l'utiliser dans votre code.


2 commentaires

Haha, quelle proposition joliment horrible. +1 Pour une réponse qui me semble plausible, bien que ce soit, comme vous admettez, pas conseillé du tout.


Cependant, cela me surviennent, cependant, cette petite assistante "utile" serait vraiment inutile si l'appelait de dans une autre fonction, car la fonction d'appel aurait toujours une référence à l'objet en question. Ce qui signifie que plutôt que isexistingingObject , il faudrait simplement dupliquer ce code partout pour l'utiliser. Yikes. Bonne chose ce n'était pas une suggestion sérieuse en premier lieu;)



3
votes

Permettez-moi de réécrire votre question à quelque chose de plus court.

Y a-t-il un moyen, dans ma méthode, qui prend un objet comme un argument, de savoir si cet objet sera jamais utilisé en dehors de ma méthode? P> blockQuote>

et la réponse courte à celle-ci est la suivante: non. strong> p>

Permettez-moi d'avouer une opinion à ce stade: il ne devrait y avoir aucun mécanisme de ce type.

Cela compliquerait les appels de méthode sur tout le lieu. P>

S'il y avait une méthode où je pouvais, dans un appel de méthode, dites si l'objet que je suis donné serait vraiment utilisé ou Pas, alors c'est un signal pour moi, en tant que développeur de cette méthode, de le prendre en compte. P>

Fondamentalement, vous verriez ce type de code partout (hypothétique, car il n'est pas ' t Disponible / pris en charge :) p> xxx pré>

mon avis est-ce: Si le code que appelle em> votre méthode ne va pas utiliser l'objet pour quoi que ce soit et il n'y a pas d'effets secondaires en dehors de la modification de l'objet, ce code ne doit pas exister pour commencer. P>

C'est comme le code qui ressemble à ceci: p>

1 + 2;


0 commentaires