11
votes

Est-il possible de cloner un appréciage?

est-il possible de cloner un objet, quand il est connu d'être un valuelette boxé, sans code de clone spécifique de type?

Certains code pour référence p>

List<ValueType> values = new List<ValueType> { 3, DateTime.Now, 23.4M }; 

// Clone
values.Add(values[values.Count() - 1]);

// Overwrite original
values[2] = 'p';

foreach (ValueType val in values)
   Console.WriteLine(val.ToString());


8 commentaires

Jon Jon Jon, sors où que tu sois ..


Finalement, vous devrez taper le "type de la variable" si vous deviez le casser. Pourriez-vous donner un exemple de ce que vous essayez d'atteindre? Le mot clé "dynamique" en C # 4 pourrait être utile ici.


Que fait duplicatelastitem?


@shahkalpeh Duplicatelastitem Duplique le dernier article, c'est là que se passe la magie "clone".


valeurs.add (valeurs [valeurs.count]? ou valeurs.add (valeurs [valeurs.Count -1]?


@shahkalpeh qui effectuerait une copie de la référence, Ian veut cloner l'instance d'objet.


@Yannick: Si je le comprends correctement, les types de valeur sont copiés par la valeur et la référence n'est pas copiée. I.E Si vous modifiez la valeur du dernier élément (après le code ci-dessus), cela n'affectera pas l'élément précédent.


@Ian: Qu'attendez-vous dans les "valeurs", après que DuplicateItem est appelé? Voulez-vous que cela se comporte de telle sorte que tout changement dans le dernier élément, entraîner une modification du "nouveau" dernier élément (c'est-à-dire celui après l'appel à duplicatevalues)?


7 Réponses :


5
votes

Chaque affectation d'un valitype est par définition un clone.

EDIT:

Lors de la boxe A valorisant une copie de votre valeurype sera contenue dans une instance d'un référencétype.

En fonction de la méthode de clonage, je ne prévoie aucune différence.


10 commentaires

Ceci est à propos des valeurs boxées non?


"Chaque affectation d'un apprécié est par définition un clone." Tort. L'affectation ne "clonge" pas un type de valeur. Vous obtenez une référence à la même valeur.


Jorge, c'est la différence fondamentale entre les valeurs de valeur et les références. int i = 1; int a = i; <- A sera un clone de i


Les valeurs boxées ne sont pas stockées dans des cas d'objet, elles ont leurs propres types de référence correspondants. Le type d'objet n'est pas le même que le type d'int32.


Brian, tu as absolument raison. J'étais trop simplifié, mais la ligne de fond est la même.


Je veux dire que les types de valeur ont des sémmantiques spéciaux afin que x = x + 1 entraîne une nouvelle valeur, et x détient une référence à cette valeur. C'est une immuabilité, interne, le CLR ne crée pas un nouvel élément sur la pile chaque fois que vous venez de faire une mission.


Yannick, je te soins (et je devine juste) en effet, je vous référez à un objet de même objet, si vous "essayez" de modifier, je vous finirez simplement de pointer vers un nouveau type de valeur afin d'avoir toujours un point sur l'ancien. .. qui éviterait beaucoup d'espace gaspillé dans la pile


Jorge, je vois ce que tu veux dire, semble plausible.


Jorge: Une chose à garder à l'esprit si la portée. En fonction de la portée de l'appréciage «copié», il peut être impossible de faire référence à la même valeur sur la pile.


Si u hérite de t , list .enumerator peut être en boîte sous la forme d'un ienumerator . En outre, la copie ou la boîte de copie d'une liste .Nenumerator à une autre valeur de ce type prendra un instantané de son état. Compte tenu d'une référence à un ienumerator Lequel sait être une liste .enumerator pour un type inconnu u , est là toute façon agréable de cloner son état?



2
votes
    private static T CloneUnboxed<T>(object o) where T : struct
    {
        return (T)o;
    }

    private static object CloneBoxed<T>(object o) where T : struct
    {
        return (object)(T)o;
    }
Although I do question the need for either, given that a value type ought to be immutable. 

0 commentaires

1
votes

Si vous deviez lancer l'objet à l'appréciage, cela ne causerait-il pas de faire fabriquer un clone? Cela pourrait alors être REBoxed:

object clone = (ValueType) boxed;


7 commentaires

Non, ce ne sera pas. J'ai testé cela, la méthode des referequaux renvoie true lors de la comparaison de B et C.


Avez-vous essayé de comparer B et D, car ce sont les deux valeurs en boîte?


Ok, j'ai essayé cela moi-même et il semble que deux opérations de boxe sur le même type de valeur résultent dans la même boîte utilisée. En y pensant, c'est un comportement sensible par le CLR.


+1 J'ai essayé cela et il semble certainement que cela fonctionne. THX.


Je l'ai essayé mais il échoue: [TestMethod] Public Void Testboxandunbox () {int i = 3; objet b = i; Valeur c = (valeur de valeur) B; objet d = c; Affirmer.arrenotsame (B, D); }


Oui, cela correspond à mes conclusions (voir mon commentaire ci-dessus). Je pense que le CLR / Compiler se réalise que la même boîte peut être réutilisée bien que, car cela doit le faire, il doit se rendre compte que le type de valeur est immuable. Je devrai enquêter plus loin. J'ai essayé de faire l'orginal Int un champ volatil, mais cela n'a pas aidé.


Le "valaettype" plutôt ironiquement nommé est un type de classe, et non un type de valeur, ce qui l'attribu à un objet copiera simplement la référence. Pensez-y comme "ValueWrapper".



3
votes

Pourquoi avez-vous besoin de code de clonage quand même? Les types de valeur devraient généralement être immuables de toute façon et cela n'est pas modifié par la boxe. Par conséquent, un type de valeur bien conçu n'a aucune exigence pour le clonage.


7 commentaires

Exactement. Il est important de formuler la question de la question et d'un exemple de code avec ce que l'on attend peut toujours aider.


Supposons que l'on ait un ienumerator lequel connaît est une liste .enumerator pour un type inconnu u qui dérive de T . Si on savait u , coulée sur Liste .enumerator prendrait un instantané de son état, mais cela nécessiterait de savoir type u u .


@supercat uhm, je pense que vous avez accidentellement commenté accidentellement sur le mauvais post. Au moins, je ne vois pas la connexion.


@KonRADRUDOLPH: Type Liste .enumerator est un type de structure auto-mutating largement utilisé qui est fréquemment en boîte. Pour certains types d'algorithmes, il peut être utile de pouvoir prendre un instantané de l'état d'un énumérateur et revenir à ce point. Clonage du type de valeur en boîte serait un moyen de le faire.


@supercat c'est un point intéressant en fait. Autant que je le vois, cependant, les énumérateurs de rembobinage ne sont tout simplement pas pris en charge par le cadre. Il fonctionnerait théoriquement dans le cas spécifique de la liste .Nenumerator (bien que non dans le cas dans le cas que vous avez décrit précédemment) mais pas en général puisque rien dans le ienumerator Interface mandats qu'il est copieux. Je comprends votre cas d'utilisation, mais même si vous avez trouvé une solution à des types de valeur clone, il ne serait pas pris en charge par .NET.


@KonRADRUDOLPH: Mon point était que la boxe d'un type de valeur ne le rend pas immuable et, tout en mutant, les types de boîte à boîte sont plutôt douteux, il existe des endroits, même dans des parties couramment utilisées du cadre, où elle se produit. Une méthode statique viseTType membre-queltypeeclone (cet apprécipe SRC) serait sémantiquement bien défini lorsqu'il serait donné de type de valeur en boîte, et serait dans certains cas sémantiquement utile (il aurait la même sémantique que l'attribution d'une variable de le type non poxed à un autre). Dans les cas où une telle fonction pourrait être utilisée, on connaîtrait généralement le type sous-jacent, mais peut-être pas toujours.


@supercat Oui, je suis d'accord avec votre point (dans ce cas très spécial). C'est un bon complément à ma réponse.



6
votes

Vous pouvez utiliser un hack à l'aide de convert.changetype : xxx

Le résultat est copie de la valeur de la valeur dans un nouvel objet.


2 commentaires

Je ne suis pas sûr des tripes du CLR mais la solution que j'ai travaille. Comme vous l'avez dit dans les commentaires à une autre réponse, vous avez probablement attrapé le CLR faisant quelque chose de "intelligent"


Cela semble être la bonne approche dans la seule situation que je puisse voir où la question a du sens: on se réfère à un objet de tas dont le type connu pour être une structure mais est autrement inconnu, et on souhaite faire un clone de celui-ci. On dirait toujours une question étrange, car on ne peut pas vraiment faire beaucoup avec un objet de tas sans connaître son type, sauf si cela implémente une interface, et si l'on définit une structure pour mettre en œuvre une interface, une interface peut également inclure un clone approprié. fonction dans cette interface.



3
votes

Je ne sais pas, si j'ai totalement mal compris la question.
Essayez-vous de faire cela? XXX


0 commentaires

2
votes

Répondre au titre et non à l'intention (au cas où une personne trouve cette question), oui, clonage d'une valeur en boîte de type par valeur est prise en charge via RuntimeHelPers.getObjectValue . Pour les types de référence, cette méthode renvoie simplement la référence d'origine, mais pour les types de valeur, cela crée un nouvel objet en boîte avec la même valeur. Pour des types de valeur immuables, cela n'est pas nécessaire, car l'instance ne doit jamais être modifiée, mais pour des types mutables, il est prudent à utiliser si vous passez l'instance au code qui pourrait le modifier.


0 commentaires