创造你自己的“int”或“字符串”班级

发布于 2024-08-28 07:16:06 字数 601 浏览 8 评论 0原文

我反汇编了 .NET“系统”DLL,并查看了变量类(字符串、整数、字节等)的源代码,看看是否可以弄清楚如何创建一个可以接受值的类。我注意到“Int32”类继承了以下内容:IComparable、IFormattable、IConvertible、IComparable、IEquatable。

String 和 Int32 类是不可继承的,我无法弄清楚这些继承的接口中的哪些内容允许这些类保存值。我想要的是这样的:

public class MyVariable : //inherits here
{
     //Code in here that allows it to get/set the value
} 

public static class Main(string[] args)
{
     MyVariable a = "This is my own custom variable!";
     MyVariable b = 2976;

     if(a == "Hello") { }
     if(b = 10) { }
     Console.WriteLine(a.ToString());
     Console.WriteLine(a.ToString());
}

I disassembled the .NET 'System' DLL and looked at the source code for the variable classes (string, int, byte, etc.) to see if I could figure out how to make a class that could take on a value. I noticed that the "Int32" class inherits the following: IComparable, IFormattable, IConvertible, IComparable, IEquatable.

The String and Int32 classes are not inheritable, and I can't figure out what in these inherited interfaces allows the classes to hold a value. What I would want is something like this:

public class MyVariable : //inherits here
{
     //Code in here that allows it to get/set the value
} 

public static class Main(string[] args)
{
     MyVariable a = "This is my own custom variable!";
     MyVariable b = 2976;

     if(a == "Hello") { }
     if(b = 10) { }
     Console.WriteLine(a.ToString());
     Console.WriteLine(a.ToString());
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

疯狂的代价 2024-09-04 07:16:06

您可以通过重载运算符来做到这一点。 MSDN 上有一个教程。

假设您想要一个可以是字符串或整数的类型(例如 Haskell 的 两者之一):

public sealed class StringOrInt32
{
    private string stringValue;
    private int int32Value;
    private bool isString;

    public bool IsString { get { return isString; } }
    public bool IsInt32 { get { return !isString; } }

    public string StringValue
    {
        get
        {
            if(!isString) throw new InvalidOperationException();
            return stringValue;
        }
    }

    public int Int32Value
    {
        get
        {
            if(isString) throw new InvalidOperationException();
            return int32Value;
        }
    }

    public StringOrInt32(string value)
    {
        isString = true;
        stringValue = value;
    }

    public StringOrInt32(int value)
    {
        isString = false;
        int32Value = value;
    }

    // Allows writing this:
    // StringOrInt32 foo = "Hello world!";
    public static implicit operator StringOrInt32(string value)
    {
        return new MyVariable(value);
    }

    // Allows writing this:
    // StringOrInt32 foo = 42;
    public static implicit operator StringOrInt32(int value)
    {
        return new MyVariable(value);
    }

    // Allows writing this:
    // StringOrInt32 foo = "Hello world!;
    // string bar = (string)foo;
    // Though foo.StringValue directly would be better
    public static explicit operator string(StringOrInt32 value)
    {
        return value.StringValule;
    }

    // Allows writing this:
    // StringOrInt32 foo = 42;
    // int bar = (int)foo;
    // Though foo.Int32Value directly would be better
    public static explicit operator int(StringOrInt32 value)
    {
        return value.Int32Value;
    }

    public static bool operator==(StringOrInt32 left, StringOrInt32 right)
    {
        if(left.IsString != right.IsString)
            return false;
        if(left.IsString)
            return left.StringValue == right.StringValue;
        else
            return left.Int32Value == right.Int32Value;
    }

    public static bool operator!=(StringOrInt32 left, StringOrInt32 right)
    {
        return !(left == right)
    }

    // Don't forget to override object.Equals(), object.GetHashCode(),
    // and consider implementing IEquatable<StringOrInt32>
    // Also, null checks, etc
}

You can do that by overloading operators. There is a tutorial on MSDN.

Let's say you want a type that can be either a string or an int (like Haskell's Either):

public sealed class StringOrInt32
{
    private string stringValue;
    private int int32Value;
    private bool isString;

    public bool IsString { get { return isString; } }
    public bool IsInt32 { get { return !isString; } }

    public string StringValue
    {
        get
        {
            if(!isString) throw new InvalidOperationException();
            return stringValue;
        }
    }

    public int Int32Value
    {
        get
        {
            if(isString) throw new InvalidOperationException();
            return int32Value;
        }
    }

    public StringOrInt32(string value)
    {
        isString = true;
        stringValue = value;
    }

    public StringOrInt32(int value)
    {
        isString = false;
        int32Value = value;
    }

    // Allows writing this:
    // StringOrInt32 foo = "Hello world!";
    public static implicit operator StringOrInt32(string value)
    {
        return new MyVariable(value);
    }

    // Allows writing this:
    // StringOrInt32 foo = 42;
    public static implicit operator StringOrInt32(int value)
    {
        return new MyVariable(value);
    }

    // Allows writing this:
    // StringOrInt32 foo = "Hello world!;
    // string bar = (string)foo;
    // Though foo.StringValue directly would be better
    public static explicit operator string(StringOrInt32 value)
    {
        return value.StringValule;
    }

    // Allows writing this:
    // StringOrInt32 foo = 42;
    // int bar = (int)foo;
    // Though foo.Int32Value directly would be better
    public static explicit operator int(StringOrInt32 value)
    {
        return value.Int32Value;
    }

    public static bool operator==(StringOrInt32 left, StringOrInt32 right)
    {
        if(left.IsString != right.IsString)
            return false;
        if(left.IsString)
            return left.StringValue == right.StringValue;
        else
            return left.Int32Value == right.Int32Value;
    }

    public static bool operator!=(StringOrInt32 left, StringOrInt32 right)
    {
        return !(left == right)
    }

    // Don't forget to override object.Equals(), object.GetHashCode(),
    // and consider implementing IEquatable<StringOrInt32>
    // Also, null checks, etc
}
云淡月浅 2024-09-04 07:16:06

C# 中的内置类型被“特殊”处理,因为代码中的文字值 1234 被定义为 System.Int32 类型,而文字值 “some string” 被定义为 System.Int32 类型。 code> 被定义为 System.String 类型。

因此,为了支持您想要的代码类型,您需要提供可以从 int 和 string(以及其他任何类型)转换为您的类型的转换运算符。查看 MSDN 中的转换运算符主题。

The built-in types in C# are handled "specially" in that the literal value 1234 in code is defined as being of type System.Int32, and the literal value "some string" is defined as being of type System.String.

So in order to support the kind of code you want, you're going to need to provide conversion operators that can convert from int and string (and whatever else) to your type. Have a look at the conversion operators topic in MSDN.

山川志 2024-09-04 07:16:06

通常,您希望创建一个新类型来存储新的数据表示形式。在上面的示例中,您使用 MyVariable 来存储字符串 - 字符串类型已经擅长这样做。

如果您想存储不同类型的数据,例如在一个易于发送的包中存储字符串和 int 的组合,您可以按照上面开始的方式进行操作:

public class MyVariable
{
    public string Name { get; set; }
    public int Age { get; set; }
} 

然后:

MyVariable personOne = new MyVariable { Name = "John", Age = 34 };
MyVariable personTwo = new MyVariable { Name = "Joe", Age = 312 };

IComparable 和 IFormattable 等接口允许您的新类型以特定方式使用,例如 IComparable 可以传递到排序列表,因为它能够将其自身与另一个实例进行比较并相应地对它们进行“排名”。

Generally you want to make a new type to store a new representation of data. In your example above you are using MyVariable to store strings - something the string type is already good at doing.

If you want to store a different type of data, such as a combination of string and int in one easy to send around package you would do it as you've started above:

public class MyVariable
{
    public string Name { get; set; }
    public int Age { get; set; }
} 

Then:

MyVariable personOne = new MyVariable { Name = "John", Age = 34 };
MyVariable personTwo = new MyVariable { Name = "Joe", Age = 312 };

Interfaces such as IComparable and IFormattable allow your new type of be used in specific ways, for instance IComparable can be passed to sorted lists as it is capable of comparing its self to another instance and 'ranking' them accordingly.

套路撩心 2024-09-04 07:16:06

“int”和“string”是内置类型。如果没有可辨别的领域,你将无法制作出类似的产品。但是,您可以创建一些外观和行为几乎与内置类型完全相同的东西。

最好的例子是Nullable。这提供了所有值类型的可为空版本,并且可以像内置一样进行分配:

int? x = 0;
int? y = null;

其工作方式是 Nullable 覆盖显式和隐式转换。通过这种方式,您可以将 int 等内置类型分配给自定义 Nullable,并且 Nullable.op_Implicit 中的代码会透明地处理转换。

这是一个完整的示例:

public struct MyVariable
{
    private int _intValue;
    private string _stringValue;

    public override bool Equals(object obj)
    {
        if (!(obj is MyVariable))
        {
            return false;
        }
        var y = (MyVariable) obj;
        return _stringValue == y._stringValue && _intValue == y._intValue;
    }

    public override int GetHashCode()
    {
        return (_stringValue ?? _intValue.ToString()).GetHashCode();
    }

    public override string ToString()
    {
        return _stringValue ?? _intValue.ToString();
    }

    public static implicit operator MyVariable(string value)
    {
        return new MyVariable { _stringValue = value };
    }

    public static implicit operator MyVariable(int value)
    {
        return new MyVariable { _intValue = value };
    }

    public static bool operator==(MyVariable variable, string value)
    {
        return variable._stringValue == value;
    }

    public static bool operator ==(MyVariable variable, int value)
    {
        return variable._intValue == value;
    }

    public static bool operator !=(MyVariable variable, string value)
    {
        return variable._stringValue == value;
    }

    public static bool operator !=(MyVariable variable, int value)
    {
        return variable._intValue == value;
    }

    public static void Test()
    {
        MyVariable a = "This is my own custom variable!";
        MyVariable b = 2976;

        if (a == "Hello") { }
        if (b == 10) { }
        Console.WriteLine(a.ToString());
        Console.WriteLine(a.ToString());
    }
}

"int" and "string" are built-in types. You won't be able to make one just like it that has no discernible fields. However, you can make something that looks and behaves almost exactly like a built-in type.

The best example is Nullable<T>. This provides a nullable version of all value types and can be assigned just like it's built in:

int? x = 0;
int? y = null;

The way this works is Nullable<T> overrides the explicit and implicit casts. This way you can assign a built-in type like int to a custom Nullable<int> and code within Nullable<int>.op_Implicit handles the conversion transparently.

Here's a complete example:

public struct MyVariable
{
    private int _intValue;
    private string _stringValue;

    public override bool Equals(object obj)
    {
        if (!(obj is MyVariable))
        {
            return false;
        }
        var y = (MyVariable) obj;
        return _stringValue == y._stringValue && _intValue == y._intValue;
    }

    public override int GetHashCode()
    {
        return (_stringValue ?? _intValue.ToString()).GetHashCode();
    }

    public override string ToString()
    {
        return _stringValue ?? _intValue.ToString();
    }

    public static implicit operator MyVariable(string value)
    {
        return new MyVariable { _stringValue = value };
    }

    public static implicit operator MyVariable(int value)
    {
        return new MyVariable { _intValue = value };
    }

    public static bool operator==(MyVariable variable, string value)
    {
        return variable._stringValue == value;
    }

    public static bool operator ==(MyVariable variable, int value)
    {
        return variable._intValue == value;
    }

    public static bool operator !=(MyVariable variable, string value)
    {
        return variable._stringValue == value;
    }

    public static bool operator !=(MyVariable variable, int value)
    {
        return variable._intValue == value;
    }

    public static void Test()
    {
        MyVariable a = "This is my own custom variable!";
        MyVariable b = 2976;

        if (a == "Hello") { }
        if (b == 10) { }
        Console.WriteLine(a.ToString());
        Console.WriteLine(a.ToString());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文