c#从int32派生

我有几个成员叫做’Id’。 本来我想把这些作为整体存储,但我想要一些保护层,以确保我不会意外地为一个人等分配房间ID。

一个解决方案是typedef(使用RoomId = System.Int32;)然后我需要使用这些代码在所有文件中。 我更喜欢例如从int32派生的RoomId类,但我无法弄清楚如何设置它以允许显式转换(用于初始化)

或者我应该以其他方式这样做?

如果我理解正确,你真正需要的唯一操作就是平等比较。 您可以创建一个RoomId类(或结构,适合您)

class RoomId { private int Value {get; set;} public RoomId(int value) { this.Value = value; } public bool Equals(RoomId other) { return this.Value == other.Value; } } RoomId room1 = new RoomId(1); RoomId room2 = new RoomId(2); // To compare for equality bool isItTheSameRoom = room1.Equals(room2); // Or if you have overloaded the equality operator (==) bool isItTheSameRoom = room1 == room2; 

您可以实现IEquatable,如果需要,可以重载相等和不等式运算符。 如果你需要持久性,你可以实现ISerializable接口,以确保整数值只在真正需要时“逃避”类。

您无法从Int32派生,但您可以指定隐式转换,这可能会为您提供所需的行为:

 public struct RoomId { private int _Value; public static implicit operator RoomId(int value) { return new RoomId { _Value = value }; } public static implicit operator int(RoomId value) { return value._Value; } } // ... RoomId id = 42; Console.WriteLine(id == 41); // False Console.WriteLine(id == 42); // True Console.WriteLine(id < 42); // False Console.WriteLine(id > 41); // True Console.WriteLine(id * 2); // 84 
  public static explicit operator RoomId(int value) { return new RoomId { Id = value }; } 

然后你可以这样做:

  RoomId variable = (RoomId)10; 

无法从Int32或C#中的任何其他值类型派生类。

您不能在.NET中inheritance值类型(结构,包括Int32)。

最接近的选择是创建一个只包含Int32的结构。 这将需要相同的空间,但可能仅限于您的确切结构。 然后,如果需要,您可以稍后更改结构以包含其他信息。 (但请注意,这可能是一个重大的API更改。)

我的偏好是使用一个简单的T4模板来动态生成自定义类型。 这是我最近在个人项目中使用的一个例子。 在第10行,是生成的类型列表。 这些东西中的每一个都是int ,但现在它们是强类型的。

这也通过避免通常的“原始痴迷”反模式,将代码转向使用更多function范例。

有我正在使用的模板。 随意更新/修改(如果你添加任何有用的东西,让我们其他人知道)。

 <#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".cs" #> <# // List of types to generate: var createTypeList = new[] { "XDim", "YDim", "YDelta", "DelayValue", "HValue", "Score", "TplIndexValue" }; #> using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.Contracts; // ReSharper disable CheckNamespace <# for(int i = 0; i < createTypeList.Length; i++) { var typeName = createTypeList[i]; #> [ImmutableObject(true)] public struct <#=typeName#> : IComparable<<#=typeName#>> { public <#=typeName#>(int value) { Value = value; } [Pure] public int Value { get; } [Pure] public bool Equals(<#=typeName#> other) => Value == other.Value; [Pure] public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (Equals(this, obj)) return true; return obj.GetType() == GetType() && Equals((<#=typeName#>)obj); } [Pure] public override int GetHashCode() { unchecked { return (base.GetHashCode() * 397) ^ Value; } } [Pure] public static bool operator ==(<#=typeName#> left, <#=typeName#> right) => Equals(left, right); [Pure] public static bool operator !=(<#=typeName#> left, <#=typeName#> right) => !Equals(left, right); [Pure] public int CompareTo(<#=typeName#> other) => Equals(this, other) ? 0 : Value.CompareTo(other.Value); [Pure] public static bool operator <(<#=typeName#> left, <#=typeName#> right) => Comparer<<#=typeName#>>.Default.Compare(left, right) < 0; [Pure] public static bool operator >(<#=typeName#> left, <#=typeName#> right) => Comparer<<#=typeName#>>.Default.Compare(left, right) > 0; [Pure] public static bool operator <=(<#=typeName#> left, <#=typeName#> right) => Comparer<<#=typeName#>>.Default.Compare(left, right) <= 0; [Pure] public static bool operator >=(<#=typeName#> left, <#=typeName#> right) => Comparer<<#=typeName#>>.Default.Compare(left, right) >= 0; [Pure] public override string ToString() => $"{nameof(Value)}: {Value}"; } <# } #>