c# deriving from int32

后端 未结 5 1291
滥情空心
滥情空心 2020-12-31 01:38

i have several classes with members called \'Id\'. Originally i wanted to store these as ints, but i would like some layer of protection, to make sure i don\'t accidentally

相关标签:
5条回答
  • 2020-12-31 01:53
     public static explicit operator RoomId(int value) {
         return new RoomId { Id = value };
     }
    

    You could then do:

     RoomId variable = (RoomId)10;
    

    It's not possible to derive a class from Int32 or any other value type in C#.

    0 讨论(0)
  • 2020-12-31 01:55

    You can't derive from Int32, but you can specify implicit conversions, which might give you the behaviour you need:

    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
    
    0 讨论(0)
  • 2020-12-31 02:09

    You cannot inherit value types (structs, including Int32) in .NET.

    The closest option would be to make a struct which contained nothing but your Int32. This would require the same space, but could be restricted to your exact struct. You could then change your struct later to include other information, if needed. (Be aware, though, that this will probably be a breaking API change.)

    0 讨论(0)
  • 2020-12-31 02:15

    If I understand correctly, the only operation you really need is comparison for equality. You can create a RoomId class (or struct, whichever suits you)

    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;
    

    You can implement IEquatable, overload the equality and inequality operators if you want. If you need persistence, you could implement the ISerializable interface to make sure that the integer value only "escapes" the class if it is really needed.

    0 讨论(0)
  • 2020-12-31 02:16

    My preference is to use a simple T4 template to generate custom types on the fly. Here's an example I used on a personal project recently. On line 10, is a list of types that are generated. Each of these things used to be int, but now they're strongly typed.

    This also moves your code toward using a more Functional paradigm by avoiding the usual "primitive obsession" anti-pattern.

    There's the template I'm using. Feel free to update/modify (let the rest of us know if you add anything useful).

    <#@ 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}";
        }
    <#
        }
    #>
    
    0 讨论(0)
提交回复
热议问题