如何提供将我的课程转换为其他类型的支持?例如,如果我有自己的管理byte[]
的实现,并且我想让人们将我的课程投放到只返回私人成员的byte[]
,那么我该怎么做?如何为我的课程提供自定义演员支持?
通常的做法是让他们也把这个字符串转换成字符串,或者我应该重写ToString()
(或两者)?
如何提供将我的课程转换为其他类型的支持?例如,如果我有自己的管理byte[]
的实现,并且我想让人们将我的课程投放到只返回私人成员的byte[]
,那么我该怎么做?如何为我的课程提供自定义演员支持?
通常的做法是让他们也把这个字符串转换成字符串,或者我应该重写ToString()
(或两者)?
您需要覆盖转换运算符,使用implicit
或explicit
,具体取决于您希望用户必须投射它还是希望它自动发生。通常,一个方向将始终有效,这就是您使用implicit
的地方,而另一个方向有时可能会失败,这就是您使用explicit
的地方。
public static implicit operator byte[] (MyType x)
{
byte[] ba = // put code here to convert x into a byte[]
return ba;
}
- :
的语法是这样的(>byte[]
永远是可行的MyType
)
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;
}
对于你的榜样,从您的自定义类型说
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;
}
我宁愿有一些方法可以做到这一点,而不是重载演员操作。
见explicit and implicit c#但要注意,从例如,使用显式的方法,如果你这样做:
string name = "Test";
Role role = (Role) name;
然后一切都很好;但是,如果你使用:
object name = "Test";
Role role = (Role) name;
现在你会得到一个InvalidCastException因为字符串不能转换到角色,为什么,编译器仅查找在根据自己的编译型编译时隐式/显式转换。在这种情况下,编译器将名称视为对象而不是字符串,因此不使用Role的重载操作符。
看看你链接到的例子,它似乎在每个演员阵容上创建对象的新实例。任何想法如何对类的当前成员进行get/set类型的操作? – esac
您可以使用explicit
或implicit
关键字在您的类上声明转换运算符。
作为一般的经验法则,当转换不可能失败时,应该只提供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;
对于自定义投射支持,您需要提供演员操作符(显式或隐式)。 EncodedString类的以下示例是使用自定义编码的字符串的简单实现(如果必须处理巨大的字符串并遇到内存消耗问题,可能会很有用,因为.Net字符串是Unicode - 每个字符需要2个字节的内存 - 和EncodedString每个字符可以占用1个字节)。
EncodedString可以转换为byte []和System.String。 代码中的注释揭示了一些光线,并解释了隐式转换可能会导致危险的示例。
通常您首先需要非常好的理由来声明任何转换运算符,因为。
更多资料请访问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();
}
}
谢谢,正是我期待的。 – esac