如何为我的课程提供自定义投射支持?

我如何提供支持将我的课程转换为其他types? 例如,如果我有我自己的pipe理一个byte[] ,我想让人们投我的类到一个byte[] ,这将只返回私人成员,我该怎么做?

是否习惯于让他们也将这个string,或者我应该重写ToString() (或两者)?

您需要重写转换运算符,可以使用implicitexplicit这取决于您希望用户必须投射它还是希望它自动发生。 一般而言,一个方向将始终工作,这就是你使用implicit的地方,而另一个方向有时会失败,这就是你explicit使用的地方。

语法是这样的:

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

要么

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

对于你的例子,从你的自定义types( MyType – > byte[]将始终工作):

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

要么

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

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

作为一般的经验法则,当转换不可能失败时,您应该只提供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; } } 

使用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; 

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

 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; 

我宁愿有一些方法可以做到这一点,而不是重载演员操作。

看到显式和隐式的c#,但请注意,从这个例子中,使用显式方法,如果你这样做:

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

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

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

您现在将得到一个InvalidCastException,因为string不能转换为angular色,为什么编译器只在编译时根据编译types查找隐式/显式转换。 在这种情况下,编译器将name视为对象而不是string,因此不使用Role的重载操作符。

对于自定义投射支持,您需要提供投射运算符(显式或隐式)。 下面的EncodedString类的例子是一个简单的string实现自定义编码(如果你必须处理巨大的string,并遇到内存消耗问题,可能是有用的,因为.NETstring是Unicode – 每个字符需要2个字节的内存 – EncodedString每个字符可以占用1个字节)。

EncodedString可以转换为byte []和System.String。 代码中的注释揭示了一些光明,并且还可以解释一个隐式转换可能是危险的例子。

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

进一步的阅读可以在MSDN上find 。

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