这可能听起来很愚蠢。我们知道我们可以将值赋给字符串变量,如下所示
String name = "myname";
字符串是引用类型,但在声明和赋值时不需要new
运算符。如果我想设计一个具有这种行为的自定义类,我将如何进行?
由于
答案 0 :(得分:5)
您正在寻找的是隐式类型转换方法(Microsoft Documentation)。举个例子,假设你有一个名为'PositiveFloat'的类自动将浮点数绑定到值> = 0,那么你可以使用以下类布局:
class PositiveFloat
{
public float val = 0.0f;
public PositiveFloat(float f)
{
val = Math.Max(f, 0.0f); //Make sure f is positive
}
//Implicitly convert float to PositiveFloat
public static implicit operator PositiveFloat(float f)
{
return new PositiveFloat(f);
}
//Implicitly convert PositiveFloat back to a normal float
public static implicit operator float(PositiveFloat pf)
{
return pf.val;
}
}
//Usage
PositiveFloat posF = 5.0f; //posF.val == 5.0f
float fl = posF; //Converts posF back to float. fl == 5.0f
posF = -15.0f; //posF.val == 0.0f - Clamped by the constructor
fl = posF; //fl == 0.0f
对于此示例,您可能还希望为+
,-
等提供隐式运算符方法,以支持此类的float和int算法。
运算符不仅限于像int这样的核心数据类型,你可以通过使用'='来隐式地从另一个类创建一个类,但是这需要开始判断上下文。 Thing t = y;
是否有意义,或者是Thing t = new Thing(y);
甚至是Thing t = y.ConvertToThing();
?随你(由你决定。
在C#的核心,基本数据类型如int,float,char等在编译器级别实现,因此我们有一些基础可以使用。字符串也是如此,即使它看起来像引用类型。这些类型如何与运算符之类的东西一起使用实际上与上面的隐式运算符相同,但是为了确保一致性,以及允许您完全用C#创建自己的“基本”类型。
答案 1 :(得分:1)
内置的“编译魔术”处理它。在引擎盖下,字符串,整数,长整数等的字面值将转换为操作,以便在运行时正确创建相应的对象或值,而无需使用运算符new
。
String
和Int32
都是类
从技术上讲,Int32
是struct
,而不是class
,但适用相同的逻辑。
答案 2 :(得分:1)
您可以使用隐式转换运算符使用您自己的类来实现这一点 - 基本上,您可以在类中定义一个可以从值创建实例的静态方法。检查一下:
public class MyClass
{
public static implicit operator MyClass (int val)
{
return new MyClass { Value = new String('!', val)};
}
public string Value {get;set;}
}
这个类包含一个字符串。从int
隐式转换时,它会使用int
个惊叹号初始化类:
MyClass obj = 5;
Console.WriteLine(obj.Value); // outputs !!!!!
答案 3 :(得分:1)
此功能称为文字常量。编译器仅支持某些类型的这些类型,其中大多数是我们非正式地称为 primitve 类型的类型。这些是:
布尔文字:true
和false
。
整数文字:int
,uint
,long
和ulong
。
文字的确切类型是通过文字后缀指定的类型,或者从文字的值推断出来(推断类型将始终是有符号类型)。
如果推断类型不是变量的声明类型,则会自动执行隐式转换(否则会引发编译时错误)。
真正的文字:float
,double
和decimal
除非文字的后缀另有指定,否则文字的类型将始终为double
。同样,如果必要且可用,将执行对声明类型的变量的隐式转换。
字符文字:'a','1','\ u1000'等
字符串文字:支持两种类型的文字字符串:常规字符串文字和逐字字符串文字:"C:\\Path"
和@"C:\Path"
。
null 文字:null
所有这些都有编译器的特定支持。你不能以任何方式用他的行为来实现你自己的类型。您可以做的是实现从上述文字之一( null 文字除外)到您的类型的隐式转换,并以某种方式模仿常数。
请记住,你只能用可视糖模仿,因为它们绝对是不是文字常量:
struct MyLiteralType
{
public static implicit MyLiteralType(int i) => new MyLiteralType(i);
}
const MyLiteralType myLiteralTypeConstant = 1; //--> compile time error.
答案 4 :(得分:-1)
您无法设计具有此类行为的class
。但是你可以设计一个struct
。而且你不需要做任何特别的事情:只需要声明它就可以实例化struct
。
对于string s = "literal"
,string是一个类,但是使用文字的实例化是由编译器专门处理的。它相当于string s = new string( literal )
。