字符串,Int32等类和赋值的行为

  • 本文关键字:赋值 Int32 字符串 c#
  • 更新时间 :
  • 英文 :


这听起来可能很愚蠢。我们知道我们可以为字符串变量赋值,如下所示。
String name = "myname";

字符串是一种引用类型,但在声明和分配值时不需要new运算符。如果我想设计具有这种行为的自定义类,我将如何进行?

谢谢

您要查找的是一种隐式类型转换方法(Microsoft文档(。例如,假设您有一个名为"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

对于此示例,您可能还希望为+-等提供隐式运算符方法,以支持此类上的浮点数和 int 算术。

运算符不仅限于像int这样的核心数据类型,你可以通过使用"="隐式地从一个类从另一个类,但这到了你需要开始判断上下文的地步。Thing t = y;有意义,还是应该Thing t = new Thing(y);甚至Thing t = y.ConvertToThing();?这取决于你。

在 C# 的核心,int、float、char 等基本数据类型是在编译器级别实现的,因此我们有某种基础可以使用。 字符串也是如此,即使它看起来像引用类型。这些类型如何与运算符等东西一起工作,实际上与上面的隐式运算符相同,以确保一致性,并允许您完全在 C# 中发明自己的"基本"类型。

内置的"编译器魔术"处理它。在后台,字符串、整数、长整型等的文本被转换为在运行时正确创建相应对象或值的操作,而无需使用运算符new

StringInt32都是类

从技术上讲,Int32是一个struct,而不是一个class,但同样的逻辑也适用。

您可以使用隐式强制转换运算符使用自己的类来实现此目的 - 基本上,您在类中定义一个静态方法,该方法可以从值创建实例。检查这个:

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 !!!!!

此功能称为文本常量。编译器仅支持某些类型的这些类型,其中大多数是我们非正式地称为基元类型。这些是:

  1. 布尔文字:truefalse

  2. 整数文字:intuintlongulong

    文本的确切类型是通过文本的后缀或从文本的值推断的指定类型(推断类型将始终是有符号类型(。

    如果推断的类型不是变量的声明类型,则会自动执行隐式转换(如果可用((否则将引发编译时错误(。

  3. 实数:floatdoubledecimal

    文本的类型将始终double,除非文本的后缀另有指定。同样,如有必要且可用,将执行对声明类型的变量的隐式转换。

  4. 字符文字:"a"、"1"、"\u1000"等。

  5. 字符串文本:
  6. 支持两种类型的文本字符串:常规字符串文本和逐字字符串文本:"C:\Path"@"C:Path"

  7. 文字:null

所有这些都有编译器的特定支持。你不能以任何方式用他的行为来实现你自己的类型。您可以做的是实现从上述文本之一(null文本除外(到您的类型的隐式转换,并以某种方式模拟文本常量。

请记住,您只能模仿视觉糖,因为它们绝对不是文字常量:

struct MyLiteralType
{
public static implicit MyLiteralType(int i) => new MyLiteralType(i);
}
const MyLiteralType myLiteralTypeConstant = 1; //--> compile time error.

您不能设计具有此类行为的class。但是你可以设计一个struct. 而且你不需要做任何特别的事情:一个struct总是可以通过声明来实例化。

至于string s = "literal",字符串是一个类,但它使用文字的实例化是由编译器专门处理的。 相当于string s = new string( literal ).

最新更新