6
votes

Casting de tableaux en C #

en C # Je travaille avec de grandes tableaux de types de valeur. Je veux pouvoir lancer des tableaux de types de valeur compatibles, par exemple: xxx

je veux bitmap2 de partager la mémoire avec bitmap1 (elles ont les mêmes représentations de bits). Je ne veux pas faire une copie.

Y a-t-il un moyen de le faire?


7 commentaires

Non, tu ne peux pas. C'est ub même en C (où vous pouvez jouer gratuitement avec la mémoire et les moulages).


@Adriano Ce n'est que UB si vous avez une désarférence le tableau de coulée. Si le tableau est renvoyé à la couleur * avant d'être déréféré, il est valide.


Seulement, je peux penser, c'est avec un danger, j'ai fait quelque chose de similaire une longue période ... laissez-moi vérifier mes vieux trucs


@kaalus vrai mais assez inutile;)


Remarque Couleur est représenté par un Valeur longue laveonly;


@ ja72 Notez que la définition de couleur est présente dans la question, contenant des champs de 4 octets. Si la question concerne le type system.drawing.color , les réponses seront différentes, éventuellement que ce n'est pas possible.


Je pense que dangereux est le moyen d'aller ici


6 Réponses :


-1
votes

Essayez ceci: xxx pré>

Vous devrez peut-être créer une méthode d'extension pour convertir couleur code> vers uint p> p>

public static uint ToUint32(this Color color) { ... }


4 commentaires

Cela ne fonctionne pas ( Pas de conversion entre sa structure et UINT ). Même si nous avons une conversion, cela en fait une copie, nous pouvons assumer OP sait le faire, mais il demande à éviter cela.


Par définition Les temps de valeurs vont faire une copie.


Non, s'il y avait (j'imagine juste, il n'y a pas) un moyen d'accéder à la couleur * car c'était uint32 * alors il n'y aura pas de copie. C'est ce que la puissance demande.


International, une couleur est un long et non un uint . Donc, vous pourriez obtenir un pointeur sur le champ de couleur Color.Value



-1
votes

Il semble que vous souhaitiez avoir une représentation différente de la même chose. La couleur dans 4 octets ou comme un uint. Cela se fait avec les syndicats de C. Il n'y a pas de construction de l'union indigène dans C # mais la fonctionnalité peut être reproduite avec des attributs StructLayout et FieldOffset. Quelque chose comme ceci: xxx

Vous pouvez ensuite utiliser votre tableau de couleurs bitmap1 pour sélectionner ce dont vous avez besoin, par exemple: xxx

aussi longtemps que vous N'appelez pas .toarray ou .tolist sur ces requêtes Linq Vous ne produisez pas une nouvelle copie du tableau BITMAP. Ces requêtes ne décrivent que comment marcher via un tableau lorsque vous utilisez la requête dans une boucle foreach par exemple.


6 commentaires

FieldOffset peut simuler un syndicat, mais ce code apportera une copie (car c'est un type de valeur).


Je ne sais pas comment C # gère ce genre de choses mais avez-vous des preuves pour votre déclaration? Et pourquoi je suis le seul à avoir voté bien que la plupart ont la même réponse ^^ j / k


bitmap1.select (c => c.r) créera une énumération de valeurs de source. Vous ne pouvez pas les modifier (car ils sont des types de valeur, vous obtenez une copie). Just Essayer.MOREVOVER C'est iEnumerable et non uint [] au besoin (et si vous ajoutez Toarray (), vous créerez une nouvelle copie nouvelle entièrement indépendante à l'original.


"Je veux que Bitmap2 partage de mémoire avec bitmap1 [...] Je ne veux pas faire une copie" Devote par op. Donc, une énumération est une option valide. J'ai supposé que le casting de l'OP demande n'est pas son objectif principal.


Mais ils sont tous deux déclarés comme des tableaux. Si vous devez consommer ces données (à moins que la performance ne soit un problème et / ou un type est corrigé car elle doit être consommée par une autre fonction immuable) ce n'est pas un tel problème, mais si vous devez les modifier, ils ne fonctionnent pas.


Vous seriez bien sûr modifier le tableau d'origine bitmap1 dans ce cas. Mes Linqs où un exemple de ce qui pourrait être fait car nous ne savons pas ce que OP veut faire :)



0
votes

n'essayez-vous pas essentiellement de traiter votre objet de couleur comme un syndicat C?

Faites ceci: P>

Color a = new Color();
uint b = a;        //Completely valid, with the implicit cast.
uint c = (uint)a;  //Also valid, but the implicit cast makes it unnecessary.


5 commentaires

Eh bien, Toarray () crée un nouveau tableau qui pourrait être considéré comme une copie d'une sorte ^^


Il veut jeter à Uint [], qui est un pointeur. Appeler Toarray () crée ce pointeur. C'est identique à un casting. Toute méthode LINQ va entraîner des pointeurs supplémentaires, peu importe quoi. Appelez simplement le SELECT sans TOARRAY () N'enregistrez rien et donne simplement une itinérable au lieu de UINT [] (ce qui est, bien sûr, également un Inumérable .


Je vois l'utilisation de clone ici: référencesSource.microsoft.com/# MSCorlib / System / Reflet / EM IT / ... qui ressemble à une copie pour moi :) Mais je pense que nous discutons de ce que l'OP signifiait avec copie. Cela dépend de lui / elle.


Yuck. C'est ce que je reçois pour supposer que c'était une simple projection. En tout cas, j'ai ajouté davantage à la réponse qui pourrait mieux fonctionner pour le cas de OP.


Le frottement est, si l'OP a besoin que UINT [] passer à une fonction externe (semble probable), il est fort probable que citoise une copie, à moins qu'il ne veuille écrire une méthode dangereuse pour écrire un tableau à l'aide des pointeurs d'origine sur les UINTS d'origine. .



4
votes

Vous pouvez accepter cela en utilisant StructLayouts pour superposer les deux tableaux. Alors que de nombreuses réponses ici ont écrit ici comment rendre la couleur-structure avoir un uint aswell, il s'agit de la conversion "tableau":

c'est le mal. Strong> p> xxx Pré>

Ceci a essentiellement deux tableaux en référence à la même emplacement mémoire. P>

Donc, si vous souhaitez obtenir le tableau des UINTS du tableau des couleurs, vous le faites comme ceci: P>

[StructLayout(LayoutKind.Sequential)] // Or explicit, but i bellieve Sequential is enough.
struct Color
{
      public byte R;

      public byte G;

      public byte B;

      public byte A;
}


8 commentaires

Comment cela fonctionnerait-il sans le faire aussi à la structure de couleurs aussi? Sans la mise en page explicite, vous ne pouvez pas savoir comment l'exécution va stocker votre structure de couleurs et que les résultats pourraient donc être imprévisibles, non?


+1 Nice Catch et c'est seulement une réponse (jusqu'à présent) qui donnent à OP la capacité d'obtenir UINT [] au lieu d'UINT *!


Je vais tellement tester cela plus tard. La structure initiale était évidente, mais je n'ai jamais pensé à le faire une autre couche. Gloire.


Je pensais que cela n'était pas autorisé lorsque les champs étant recouverts étaient des références d'objet, mais craignait si cela ne fonctionnait pas. Agréable! (et oui, mal, mal!)


Le débogueur n'aime pas beaucoup cette approche. Il a beaucoup de mal à comprendre ce qui se passe lorsque vous essayez d'évaluer.


Même avec Linqpad, demandez-lui de vider la gamme d'unités et de sortir des couleurs :)


Je ne sais pas pourquoi les gens l'appellent mal. La couleur est faite d'octets, de manière efficace, une gamme de couleurs est une gamme d'octets, 4 fois plus grand. Je peux traiter une seule couleur comme 4 octets facilement, et c'est parfois très utile, je ne sais pas pourquoi faire de la même manière que la matrice totale devrait être si difficile et mal. Je pense que la langue devrait avoir une installation pour cela. Toute structure qui n'a pas de membres privés et que tous les membres sont des pods devraient être istaillés à toute autre structure qui répond aux mêmes conditions - et cela devrait s'étendre aux tableaux tant que les tailles correspondent.


Je l'ai appelé comme ça depuis que le débogueur n'aime pas cela et cela ressemble bien à des choses que vous faites habituellement en C #.



1
votes

Oui, vous pouvez le faire, mais avec la structure comme affichée, cela peut fonctionner juste par hasard.

Vous devez absolument ajouter des attributs à votre structure afin de vous assurer qu'il n'y a aucun rembourrage ajouté. P>

Quoi qu'il en soit, voici un programme LINQPAD qui démontre: P>

unsafe void Main()
{
    Color[] c = new Color[2]
    {
        new Color { R = 255, G = 0, B = 0, A = 0 },
        new Color { R = 0, G = 255, B = 0, A = 0 }
    };
    c.Dump();


    fixed (byte* p = &c[0].R)
    {
        uint* i = (uint*)p;
        *i = 0x11223344;
        *(i + 1) = 0x55667788;
    };
    c.Dump();
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Color
{
    public byte R, G, B, A;
}


0 commentaires

0
votes

Cela devrait faire ce que vous voulez, vous en changez un, il modifie les deux référence xxx


0 commentaires