制作自己的“int”或“string”类

时间:2010-04-06 01:48:31

标签: .net string variables int inheritance

我反汇编了.NET'System'DLL并查看了变量类(string,int,byte等)的源代码,看看我是否能弄清楚如何创建一个可以接受值的类。我注意到“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());
}

4 个答案:

答案 0 :(得分:7)

您可以overloading operators执行此操作。 MSDN上有一个教程。

假设你想要一个可以是字符串或int的类型(如Haskell的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
}

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

“int”和“string”是内置类型。你将无法制作一个没有可识别字段的产品。但是,您可以制作外观和行为几乎完全类似于内置类型的内容。

最好的例子是Nullable<T>。这提供了所有值类型的可空版本,并且可以像它内置的那样分配:

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

这种方式有效Nullable<T>会覆盖显式和隐式强制转换。这样,您就可以为自定义Nullable<int>分配内置类型(如int),Nullable<int>.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());
    }
}

答案 3 :(得分:1)

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

如果你想在一个易于发送的软件包中存储不同类型的数据,例如string和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可以传递给排序列表,因为它能够将自己与另一个实例进行比较并相应地“排名”它们。