27 Stimmen

c# Ableitung von int32

Ich habe mehrere Klassen mit Mitgliedern namens 'Id'. Ursprünglich wollte ich diese als Ints zu speichern, aber ich möchte eine Ebene des Schutzes, um sicherzustellen, dass ich nicht versehentlich eine Raum-ID zu einer Person usw. zuweisen.

eine Lösung wäre typedef (using RoomId = System.Int32;), aber dann brauche ich diese Codezeile in allen Dateien, die diese verwenden. ich würde z.B. eine RoomId-Klasse bevorzugen, die von int32 abgeleitet ist, aber ich kann nicht herausfinden, wie ich sie einrichten kann, um eine explizite Konvertierung (für die Initialisierung) zu ermöglichen

oder sollte ich dies auf andere Weise tun?

48voto

LukeH Punkte 251752

Sie können nicht von Int32 Sie können jedoch implizite Konvertierungen angeben, die das gewünschte Verhalten bewirken können:

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

9voto

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

Das könnten Sie dann tun:

 RoomId variable = (RoomId)10;

Es ist nicht möglich, eine Klasse abzuleiten von Int32 oder jeden anderen Werttyp in C#.

7voto

Tamas Czinege Punkte 114595

Wenn ich es richtig verstehe, ist die einzige Operation, die Sie wirklich brauchen, der Vergleich auf Gleichheit. Sie können eine RoomId-Klasse (oder Struktur, je nachdem, was Ihnen passt) erstellen

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;

Sie können IEquatable implementieren und die Gleichheits- und Ungleichheitsoperatoren überladen, wenn Sie wollen. Wenn Sie Persistenz benötigen, könnten Sie die Schnittstelle ISerializable implementieren, um sicherzustellen, dass der Integer-Wert die Klasse nur dann "verlässt", wenn er wirklich benötigt wird.

2voto

Reed Copsey Punkte 536986

Sie können in .NET keine Werttypen (Structs, einschließlich Int32) erben.

Die naheliegendste Möglichkeit wäre, eine Struktur zu erstellen, die nichts anderes als Ihre Int32 enthält. Dies würde den gleichen Platz benötigen, aber könnte auf Ihre genaue Struktur beschränkt werden. Sie könnten dann Ihre Struktur später ändern, um andere Informationen aufzunehmen, falls erforderlich. (Seien Sie sich jedoch bewusst, dass dies wahrscheinlich eine brechende API-Änderung sein wird).

1voto

zumalifeguard Punkte 8227

Ich bevorzuge es, eine einfache T4-Vorlage zu verwenden, um benutzerdefinierte Typen im Handumdrehen zu erstellen. Hier ist ein Beispiel, das ich kürzlich in einem persönlichen Projekt verwendet habe. In Zeile 10 befindet sich eine Liste von Typen, die generiert werden. Jedes dieser Dinge war früher int , aber jetzt sind sie stark typisiert.

Dadurch wird Ihr Code auch in Richtung eines funktionalen Paradigmas bewegt, indem das übliche Anti-Muster der "primitiven Besessenheit" vermieden wird.

Das ist die Vorlage, die ich verwende. Sie können sie gerne aktualisieren/verändern (lassen Sie uns wissen, wenn Sie etwas Nützliches hinzufügen).

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X