c#从int32派生

时间:2009-05-11 22:01:21

标签: c#

我有几个成员名为'Id'的课程。最初我想将这些存储为整数,但我想要一些保护层,以确保我不会意外地为一个人分配房间ID等。

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

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

5 个答案:

答案 0 :(得分:32)

您无法从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

答案 1 :(得分:9)

 public static explicit operator RoomId(int value) {
     return new RoomId { Id = value };
 }

然后你可以这样做:

 RoomId variable = (RoomId)10;

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

答案 2 :(得分:7)

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

我的偏好是使用简单的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}";
    }
<#
    }
#>