考虑这样一个类:
public class MyString
{
private string _string;
public string String
{
get { return _string; }
set { _string = value; }
}
public MyString(string s)
{
_string = s;
}
public static implicit operator string(MyString str)
{
return str.String;
}
public static implicit operator MyString(string str)
{
return new MyString(str);
}
}
如何使以下代码生效?
MyString a = "test";
object b = a;
var c = (string)b;
现在我得到了这个例外:
InvalidCastException:无法将“MyString”类型的对象强制转换为“System.String”。
答案 0 :(得分:4)
自定义隐式/显式运算符仅适用于类型值 - 而不是object
。这样的演员表总是基本的类型检查或unbox。隐式演员是:
string s = a;
答案 1 :(得分:2)
您可以尝试将最后一行更改为:
string c = (string)((MyString)b);
答案 2 :(得分:2)
自定义演员是一种伪装的功能。是否执行实际强制转换或调用自定义转换运算符取决于正在强制转换的表达式的编译时类型。
在您的示例中,正在转换的表达式的编译时类型即。表达式b
的类型为object
,类型object
没有自定义转换为字符串。但是,强制转换可能有效,因此编译器允许这样做。
MyString a = "test";
object b = a;
var c = (string)b;
string d = a;
var e = (string)a;
第四行将被视为 //调用定义为自定义转换的函数 string d = MyString.op_implicit(a);
第五行也是如此。第五行虽然它使用语法进行演员不是一个演员,但它是一个转换。
然而,第三行看起来像一个演员并且是演员。演员表示你告诉编译器你有关于对象的运行时类型的更多信息而不是编译。 (string)a
告诉编译器它可以放心,a表示的对象将具有字符串的运行时类型。在你的情况下,它不是真的,它的类型MyString
不是从字符串派生的(因为字符串是密封的,所以不能)。
关键是尽管自定义转换(使用隐式或显式定义)具有与强制转换相同的语法,但它们与强制转换完全不同。 演员表永远不会离开继承链(包括继承接口)你可以使用演员表上下链接但是永远不会离开它
答案 3 :(得分:-1)
你应该尝试:
public MyString:String
{
//code
}