【问题标题】:Making your own "int" or "string" class制作自己的“int”或“string”类
【发布时间】:2010-04-06 01:48:31
【问题描述】:

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

【问题讨论】:

  • 我可以编译,但是...为什么?
  • 另外,第二个 if 缺少 =(应该是 b == 10
  • 在上面代码的第12行,应该是if(b == 10) {}而不是if(b = 10) {}
  • 抱歉出现错误,它不是用来编译的。只是一个简单的例子,展示了我想要它做什么。我在底部附近找到了答案(重载运算符)。
  • 既然你说的答案在 cmets 中是正确的,你应该接受一个作为正确答案(点击复选标记)。

标签: .net string variables int inheritance


【解决方案1】:

您可以通过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
}

【讨论】:

  • 谢谢!就像其他答案之一一样,这正是我想要的。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    通常您希望创建一个新类型来存储数据的新表示。在上面的示例中,您使用 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 可以传递给排序列表,因为它能够将自身与另一个实例进行比较并相应地对它们进行“排名”。

    【讨论】:

      【解决方案4】:

      “int”和“string”是内置类型。您将无法制造出像它一样没有可识别领域的产品。但是,您可以制作看起来和行为几乎与内置类型完全相同的东西。

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

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

      它的工作方式是Nullable&lt;T&gt; 覆盖显式和隐式转换。这样,您可以将 int 等内置类型分配给自定义 Nullable&lt;int&gt;Nullable&lt;int&gt;.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());
          }
      }
      

      【讨论】:

      • Nullable 实际上有一些在 C# 中无法模拟的额外魔法:提升运算符。
      • 谢谢!这正是我想要的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      • 2019-08-12
      • 1970-01-01
      • 2020-09-17
      相关资源
      最近更新 更多