Behavior of String, Int32 and Classes

This may sound silly. We know that we can assign a value to a string variable as follows. String name = "myname";

String is a reference type, but does not require an operator new

when declaring and assigning a value. If I want to create a custom class with this behavior, how can I proceed?

thank

+3


source to share


5 answers


What you are looking for is an implicit type conversion method ( Microsoft Documentation ). As an example, suppose you have a class called PositiveFloat that automatically binds floats to values> = 0, then you can have the following class layout:

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

      

In this example, you also probably want to provide implicit operator methods for +

, -

etc. to support float and int arithmetic in this class.



Operators are not just limited to basic data types like int, but you can implicitly make one class out of another just by using '=', but that gets to the point where you need to start judging the context. Does it make sense Thing t = y;

, or should it be, Thing t = new Thing(y);

or even Thing t = y.ConvertToThing();

? This is for you.

At the heart of C #, basic data types like int, float, char, etc. are implemented at the compiler level, so we have some kind of base to work with. a string too, although it looks like a reference type. How these types work with things like operators, etc. is almost identical to the implicit operator, but for consistency, and also allows you to completely create your own "base" types in C #.

+5


source


There is built-in compiler magic associated with it. Under the hood are literals for strings, integers, lengths, etc. Are converted to operations to correctly create the corresponding object or value at run time without using an operator new

.

Both String

and Int32

are classes



Technically, Int32

it is struct

, not class

, but the same logic applies.

+1


source


You can achieve this with your own classes using implicit cast operators - basically you define a static method in your class that can instantiate from a value. Check it:

public class MyClass
{
   public static implicit operator MyClass (int val)
   {
       return new MyClass { Value = new String('!', val)};
   }
   public string Value {get;set;}
}

      

This class contains a string. When implicitly discarded from, int

it initializes the class with the number of exclamation marks int

:

MyClass obj = 5;
Console.WriteLine(obj.Value); // outputs !!!!!

      

+1


source


This function is called literal constants. The compiler only supports them for a few types, most of them are what we informally call primitive types. It:

  • Boolean literals: true

    and false

    .

  • Integer literals: int

    , uint

    , long

    and ulong

    .

    The exact type of a literal is the specified type via a literal suffix or inferred from the literal value (the inferred type will always be a signed type).

    If the inferred type is not the declared type of the variable, the implicit conversion is automatically performed if available (otherwise a compile-time error occurs).

  • Real literals: float

    , double

    anddecimal

    The literal type will always be double

    , unless the literal suffix is ​​specified otherwise. Again, implicit conversion to the declared type of variables will be done, if necessary and available.

  • Character literals: 'a', '1', '\ u1000', etc.

  • String literals: Two types of literals are supported: regular string literals and string literals: "C:\\Path"

    and @"C:\Path"

    .

  • Null literal: null

They all have some compiler support. You cannot implement your own behavior in any way. What you can do is implement an implicit conversion from one of the above literals (other than a null literal) to your type and simulate in some kind of literal constants.

Keep in mind that you are only mimicking visual sugar, because they are most definitely not literal constants:

struct MyLiteralType
{
     public static implicit MyLiteralType(int i) => new MyLiteralType(i);
}

const MyLiteralType myLiteralTypeConstant = 1; //--> compile time error.

      

+1


source


You cannot create class

with this behavior. But you can create struct

. And you don't need anything special: A struct

can always be created by simply declaring it.

As for string s = "literal"

, a string is a class, but creating it using a literal is handled specifically by the compiler. This is equivalent string s = new string( literal )

.

-1


source







All Articles