C# 我如何为我的班级提供自定义演员表支持?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1407689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 16:12:24  来源:igfitidea点击:

How do I provide custom cast support for my class?

c#casting

提问by esac

How do I provide support for casting my class to other types? For example, if I have my own implementation of managing a byte[], and I want to let people cast my class to a byte[], which will just return the private member, how would I do this?

我如何为将我的类转换为其他类型提供支持?例如,如果我有自己的管理 a 实现byte[],并且我想让人们将我的类转换为 a byte[],这将只返回私有成员,我该怎么做?

Is it common practice to let them also cast this to a string, or should I just override ToString()(or both)?

让他们也将其转换为字符串是常见的做法,还是我应该覆盖ToString()(或两者)?

采纳答案by Charles Bretana

You would need to override the conversion operator, using either implicitor explicitdepending on whether you want users to have to cast it or whether you want it to happen automagically. Generally, one direction will always work, that's where you use implicit, and the other direction can sometimes fail, that's where you use explicit.

您需要覆盖转换运算符,使用implicitexplicit取决于您是希望用户必须强制转换还是希望它自动发生。一般来说,一个方向总是有效,那就是你使用的地方implicit,而另一个方向有时会失败,那就是你使用的地方explicit

The syntax is like this:

语法是这样的:

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

or

或者

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

For your example, say from your custom Type (MyType--> byte[]will always work):

对于您的示例,从您的自定义类型说(MyType-->byte[]将始终有效):

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

or

或者

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;
}

回答by Chris Chilvers

I prefer to have some method that will do that rather than overloading the cast operator.

我更喜欢有一些方法可以做到这一点,而不是重载强制转换运算符。

See explicit and implicit c#but note that from that example, using the explicit method, if you do:

请参阅显式和隐式 c#,但请注意,从该示例中,使用显式方法,如果您这样做:

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

Then everything is fine; however, if you use:

那么一切都很好;但是,如果您使用:

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

You will now get an InvalidCastException because string cannot be cast to Role, why, the compiler only looks for implicit/explicit casts at compile time based upon their compiled type. In this case the compiler sees name as an object rather than string, and thus doesn't use Role's overloaded operator.

你现在会得到一个 InvalidCastException 因为字符串不能被转换为 Role,为什么,编译器只在编译时根据它们的编译类型查找隐式/显式转换。在这种情况下,编译器将 name 视为对象而不是字符串,因此不使用 Role 的重载运算符。

回答by LukeH

You can declare conversion operators on your class using either the explicitor implicitkeywords.

您可以使用explicitorimplicit关键字在您的类上声明转换运算符。

As a general rule-of-thumb, you should only provide implicitconversion operators when the conversion can't possibly fail. Use explicitconversion operators when the conversion might fail.

作为一般经验法则,您应该只implicit在转换不可能失败时才提供转换运算符。explicit当转换可能失败时使用转换运算符。

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;
    }
}

Using explicitmeans that users of your class will need to do an explicit conversion:

使用explicit意味着您的类的用户需要进行显式转换:

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;

Using implicitmeans that users of your class don't need to perform an explicit conversion, it all happens transparently:

Usingimplicit意味着您的类的用户不需要执行显式转换,这一切都是透明的:

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;

回答by Konstantin Spirin

For custom cast support you need to provide cast operators (explicit or implicit). The following example of EncodedString class is a simplistic implementation of string with custom encoding (may be useful if you have to process huge-huge strings and run into memory consumption problems because .Net strings are Unicode - every character takes 2 bytes of memory - and EncodedString can take 1 byte per char).

对于自定义转换支持,您需要提供转换运算符(显式或隐式)。EncodedString 类的以下示例是具有自定义编码的字符串的简单实现(如果您必须处理巨大的字符串并遇到内存消耗问题,这可能很有用,因为 .Net 字符串是 Unicode - 每个字符占用 2 个字节的内存 - 和EncodedString 每个字符可以占用 1 个字节)。

EncodedString can be converted to byte[] and to System.String. Comments in code shed some light and also explain an example when implicit conversion can be dangerous.

EncodedString 可以转换为 byte[] 和 System.String。代码中的注释阐明了一些情况,并解释了隐式转换可能是危险的示例。

Usually you need a very good reason to declare any conversion operators in the first place because.

通常你首先需要一个很好的理由来声明任何转换运算符,因为。

Further reading is available on MSDN.

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();
    }
}