120 votes

Comment puis-je personnaliser le cast de soutien pour les élèves de ma classe?

Comment puis-je fournir un soutien pour la coulée de ma classe à d'autres types? Par exemple, si j'ai ma propre mise en œuvre de la gestion d'un byte[], et je veux que les gens en fonte de ma classe à un byte[], qui va juste retourner le membre privé, comment pourrais-je faire cela?

Il est de pratique courante de laisser aussi lancer cette chaîne, ou devrais-je remplacer ToString() (ou les deux)?

130voto

Charles Bretana Points 59899

Vous auriez besoin de surcharger l'opérateur de conversion, en utilisant soit implicite ou explicite, selon que vous souhaitez que les utilisateurs d'avoir à jeter, ou si vous voulez que cela se produise automatiquement... en Général, une direction fonctionnera toujours, c'est l'endroit où vous utilisez implicite, et l'autre sens peut parfois échouer... c'est là que vous utilisez explicite... la syntaxe ressemble à ceci:

   public static implicit operator dbInt64(Byte x)  
    {return new dbInt64(x);}

ou

   public static explicit operator Int64(dbInt64 x) 
   {
       if (!x.defined) throw new DataValueNullException();
       return x.iVal;
   }

Pour votre exemple, dire à partir de votre Type personnalisé (MyType --> byte[] le sera toujours...

   public static implicit operator byte[] (MyType x)  
   { 
      byte[] ba = // here put code to convert x into a byte[]
      return ba;
   }

ou

   public static explicit operator MyType(byte[] x) 
   {
       if (!CanConvert) throw new DataValueNullException();
       // Factory to convert byte[] x into MyType
       MyType mt = MyType.Factory(x);  
       return mt ;
   }

39voto

LukeH Points 110965

Vous pouvez déclarer des opérateurs de conversion sur votre classe en utilisant soit l' explicit ou implicit mots-clés.

Comme une règle générale de pouce, vous ne devez fournir implicit opérateurs de conversion lors de la conversion ne peut pas échouer. Utiliser explicit opérateurs de conversion lors de la conversion peut échouer.

public class MyClass
{
    private byte[] _bytes;

    // change explicit to implicit depending on what you need
    public static explicit operator MyClass(byte[] b)
    {
        MyClass m = new MyClass();
        m._bytes = b;
        return m;
    }

    // change explicit to implicit depending on what you need
    public static explicit operator byte[](MyClass m)
    {
        return m._bytes;
    }
}

À l'aide de explicit signifie que les utilisateurs de votre classe aurez besoin de faire une conversion explicite:

byte[] foo = new byte[] { 1, 2, 3, 4, 5 };
// explicitly convert foo into an instance of MyClass...
MyClass bar = (MyClass)foo;
// explicitly convert bar into a new byte[] array...
byte[] baz = (byte[])bar;

À l'aide de implicit signifie que les utilisateurs de votre classe n'avez pas besoin d'effectuer une conversion explicite, tout se passe de manière transparente:

byte[] foo = new byte[] { 1, 2, 3, 4, 5 };
// imlpicitly convert foo into an instance of MyClass...
MyClass bar = foo;
// implicitly convert bar into a new byte[] array...
byte[] baz = bar;

7voto

Chris Chilvers Points 3882

Je préfère avoir une méthode qui fera que, plutôt que de surcharger l'opérateur de cast.

Voir http://stackoverflow.com/questions/1176641/explicit-and-implicit-c mais notez qu'à partir de cet exemple, à l'aide de la méthode explicite, si vous n':

string name = "Test";
Role role = (Role) name;

Alors tout va bien; toutefois, si vous utilisez:

object name = "Test";
Role role = (Role) name;

Vous obtiendrez alors un InvalidCastException parce que la chaîne ne peut pas être casté pour le Rôle, pourquoi, le compilateur cherche implicite/explicite jette au moment de la compilation selon leur type compilé. Dans ce cas, le compilateur voit nom comme un objet plutôt que de la chaîne, et donc n'utilise pas le Rôle de l'opérateur surchargé.

3voto

Konstantin Spirin Points 5347

Pour personnalisé en fonte soutien dont vous avez besoin pour fournir des opérateurs de transtypage (explicite ou implicite). L'exemple suivant de EncodedString classe est une approche simpliste de la mise en œuvre de la chaîne de codage personnalisé (peut être utile si vous avez à traiter énorme-énorme chaînes et de les exécuter dans la mémoire de la consommation des problèmes parce que .Net chaînes Unicode, chaque personnage prend 2 octets de mémoire - et EncodedString peut prendre de 1 octet par caractère).

EncodedString peut être converti byte[] et du Système.Chaîne de caractères. Les commentaires dans le code de jeter un peu de lumière et expliquer un exemple lors de la conversion implicite peut être dangereux.

Habituellement, vous devez avoir une très bonne raison de déclarer tous les opérateurs de conversion en premier lieu parce que.

Plus de lecture est disponible sur MSDN.

class Program
{
    class EncodedString
    {
        readonly byte[] _data;
        public readonly Encoding Encoding;

        public EncodedString(byte[] data, Encoding encoding)
        {
            _data = data;
            Encoding = encoding;
        }

        public static EncodedString FromString(string str, Encoding encoding)
        {
            return new EncodedString(encoding.GetBytes(str), encoding);
        }

        // Will make assumption about encoding - should be marked as explicit (in fact, I wouldn't recommend having this conversion at all!)
        public static explicit operator EncodedString(byte[] data)
        {
            return new EncodedString(data, Encoding.Default);
        }

        // Enough information for conversion - can make it implicit
        public static implicit operator byte[](EncodedString obj)
        {
            return obj._data;
        }

        // Strings in .Net are unicode so we make no assumptions here - implicit
        public static implicit operator EncodedString(string text)
        {
            var encoding = Encoding.Unicode;
            return new EncodedString(encoding.GetBytes(text), encoding);
        }

        // We have all the information for conversion here - implicit is OK
        public static implicit operator string(EncodedString obj)
        {
            return obj.Encoding.GetString(obj._data);
        }
    }

    static void Print(EncodedString format, params object[] args)
    {
        // Implicit conversion EncodedString --> string
        Console.WriteLine(format, args);
    }

    static void Main(string[] args)
    {
        // Text containing russian letters - needs care with Encoding!
        var text = "Привет, {0}!";

        // Implicit conversion string --> EncodedString
        Print(text, "world");

        // Create EncodedString from System.String but use UTF8 which takes 1 byte per char for simple English text
        var encodedStr = EncodedString.FromString(text, Encoding.UTF8);
        var fileName = Path.GetTempFileName();

        // Implicit conversion EncodedString --> byte[]
        File.WriteAllBytes(fileName, encodedStr);

        // Explicit conversion byte[] --> EncodedString
        // Prints *wrong* text because default encoding in conversion does not match actual encoding of the string
        // That's the reason I don't recommend to have this conversion!
        Print((EncodedString)File.ReadAllBytes(fileName), "StackOverflow.com");

        // Not a conversion at all. EncodingString is instantiated explicitly
        // Prints *correct* text because encoding is specified explicitly
        Print(new EncodedString(File.ReadAllBytes(fileName), Encoding.UTF8), "StackOverflow.com");

        Console.WriteLine("Press ENTER to finish");
        Console.ReadLine();
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X