代码之家  ›  专栏  ›  技术社区  ›  second

C源自Int32

c#
  •  15
  • second  · 技术社区  · 16 年前

    我有几个班级的成员叫“ID”。最初我想把这些存储为ints,但我想要一些保护层,以确保我不会意外地为一个人分配房间ID等。

    一个解决方案是typedef(使用roomid=System.Int32;),但是在所有使用这些的文件中,我都需要这行代码。我更喜欢从Int32派生的RoomID类,但我不知道如何将其设置为允许显式转换(用于初始化)

    或者我应该用其他方法来做这个?

    5 回复  |  直到 7 年前
        1
  •  8
  •   Tamas Czinege    16 年前

    如果我理解正确的话,你真正需要做的就是比较平等。您可以创建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接口,以确保整数值仅在确实需要时“转义”类。

        2
  •  30
  •   LukeH    16 年前

    你不能从 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
    
        3
  •  9
  •   Mehrdad Afshari    16 年前
     public static explicit operator RoomId(int value) {
         return new RoomId { Id = value };
     }
    

    你可以这样做:

     RoomId variable = (RoomId)10;
    

    不可能从 Int32 或任何其他值类型。

        4
  •  2
  •   Reed Copsey    16 年前

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

    最接近的选项是生成一个只包含Int32的结构。这将需要相同的空间,但可以限制为精确的结构。然后,如果需要,可以稍后更改结构以包含其他信息。(不过,请注意,这可能是一个破坏性的API更改。)

        5
  •  1
  •   Eagle-Eye Ed DeGagne    7 年前

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

    这还通过避免常见的“原始的困扰”反模式,将代码转向使用更实用的范式。

    这是我使用的模板。请随时更新/修改(如果您添加了任何有用的内容,请通知我们其他人)。

    <#@ 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}";
        }
    <#
        }
    #>