2009-05-11 9 views
13

से प्राप्त होने वाला # मेरे पास 'आईडी' नामक सदस्यों के साथ कई कक्षाएं हैं। मूल रूप से मैं इन्हें इनट्स के रूप में स्टोर करना चाहता था, लेकिन मुझे यह सुनिश्चित करने के लिए सुरक्षा की कुछ परत चाहिए कि मैं किसी व्यक्ति को गलती से कमरे आईडी निर्दिष्ट नहीं करता हूं।सी # int32

एक समाधान टाइपिफ़ (कक्ष Id = सिस्टम का उपयोग करके) होगा। Int32;) लेकिन फिर मुझे इन फ़ाइलों का उपयोग करके सभी फाइलों में कोड की उस पंक्ति की आवश्यकता है। मैं पसंद करूंगा उदा। int32 से व्युत्पन्न एक RoomId क्लास, लेकिन मैं यह नहीं समझ सकता कि स्पष्ट रूपांतरण (initilisation के लिए)

या मुझे इसे किसी अन्य तरीके से करना चाहिए?

उत्तर

7

यदि मैं सही ढंग से समझता हूं, तो आपको केवल एक ही ऑपरेशन की आवश्यकता है जो समानता के लिए तुलना है। आप एक RoomId वर्ग (या struct, जो भी आप सूट)

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 इंटरफ़ेस को कार्यान्वित कर सकते हैं कि पूर्णांक मान केवल कक्षा से "बच निकले" यदि वास्तव में इसकी आवश्यकता हो।

+0

निजी मूल्य के पास कोई प्रकार नहीं है? क्या वह सही है? – bendewey

+0

@bendewey: वह एक टाइपो था। इस पर ध्यान दिलाने के लिए धन्यवाद। –

+0

उत्कृष्ट, धन्यवाद! एक फॉलोअप है। चूंकि कुछ अलग-अलग आईडी की ज़रूरत है, ऐसा लगता है कि मेरे पास एक मास्टर आईडी क्लास होना चाहिए जो यह सब करता है, और उसके बाद बस उप-आईडी प्राप्त करता है।लेकिन ऐसा लगता है कि यह काम नहीं करता है जैसा मैंने सोचा था। आईडी के लिए ऊपर का नाम बदलने और सार्वजनिक वर्ग ParticipantID लेखन: आईडी {} एक त्रुटि देता है: – second

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

फिर आप कर सकता है:

RoomId variable = (RoomId)10; 

यह Int32 या सी # में किसी भी अन्य मान प्रकार से एक वर्ग प्राप्त करने के लिए संभव नहीं है।

+0

क्या मुझे myRoom.Id.id का उपयोग करके इसे एक्सेस करना होगा? मैं इसे काम करना चाहता हूं जैसे कि यह एक int था, यानी सिर्फ myRoom.Id, उनकी तुलना करने में सक्षम हो (जो उनके मूल्यों की तुलना करेगा आदि) – second

+0

नहीं, myRoom.Id काम करेगा। आप दूसरे उत्तर में वर्णित समानता तुलनाकर्ता को भी कार्यान्वित कर सकते हैं। –

2

आप .NET में मूल्य प्रकार (Intcts सहित structs) का वारिस नहीं कर सकते हैं।

निकटतम विकल्प एक ऐसी संरचना बनाना होगा जिसमें आपके Int32 के अलावा कुछ भी न हो। इसके लिए एक ही स्थान की आवश्यकता होगी, लेकिन आपकी सटीक संरचना तक सीमित हो सकती है। यदि आवश्यक हो तो आप अन्य जानकारी को शामिल करने के लिए बाद में अपनी संरचना बदल सकते हैं। (हालांकि, यह जागरूक रहें कि यह शायद एक ब्रेकिंग एपीआई परिवर्तन होगा।)

26

आप 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 
+0

उत्कृष्ट समाधान –

+0

ग्रेट, निश्चित रूप से आवश्यक प्रत्येक विधि और ऑपरेटर को ओवरराइड करने से अधिक संक्षिप्त है। – Shocked

+0

ग्रेट समाधान। मैं एक 'आईक्वेटेबल' कार्यान्वयन भी जोड़ूंगा। – sdgfsdh

1

मेरी प्राथमिकता पर कस्टम प्रकार उत्पन्न करने के लिए एक सरल टी -4 टेम्पलेट का उपयोग करने के लिए है उड़ना। यहां एक उदाहरण है जिसका मैंने हाल ही में एक निजी परियोजना पर उपयोग किया था। लाइन 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}"; 
    } 
<# 
    } 
#> 
+0

मैंने वास्तव में आपके उत्तर से पहले टी 4 टेम्पलेटिंग के बारे में कभी नहीं सुना था। निश्चित रूप से खुशी है कि मैं इसे भर में ठोकर खाई। मैंने एक संकलन त्रुटि को ठीक करने के लिए एक छोटा सा संपादन किया जो मुझे मिल रहा था। जहां तक ​​मैं कह सकता हूं कि यह मान्य होने के बावजूद, ऐसा लगता है कि कन्स्ट्रक्टर की स्थापना की तरह ऐसा नहीं लगता था, इसलिए मैंने इसे अधिक पारंपरिक वाक्यविन्यास का उपयोग किया। –

+0

ईगल-आई, योगदान के लिए धन्यवाद। कोड परिवर्तन पर कोई मुद्दा नहीं, लेकिन ईमानदार होने के लिए, मुझे यकीन नहीं है कि आपका विरोध वास्तव में क्या था। यदि यह सी # 6 सिंटैक्स था, तो मैं उम्मीद करता था कि आप बराबर() विधि, साथ ही वर्ग के निचले हिस्से में शेष विधियों को भी बदल दें। विशेष रूप से विभिन्न वाक्यविन्यास का उपयोग करने के लिए कन्स्ट्रक्टर को सिंगल आउट क्यों करें? मुझे लगता है कि मुझे कुछ याद आ रहा है। – zumalifeguard

+0

जैसा कि मैंने कहा था, संकलक सी # 6 सिंटैक्स का उपयोग करके कन्स्ट्रक्टर के साथ त्रुटियों को फेंक रहा था, भले ही मैं कह सकता हूं कि वैध है। Intellisense कहते हैं 'सार्वजनिक XDim (int मान) => मूल्य = मूल्य; 'XDim.XDim (int)' को एक शरीर घोषित करना चाहिए क्योंकि यह सार, बाहरी, या आंशिक 'चिह्नित नहीं है,' निर्माता के पास शरीर होना चाहिए ', और 'नाम' मान 'वर्तमान संदर्भ में मौजूद नहीं है।', दूसरों के बीच। अजीब यह केवल निर्माता के साथ कोई समस्या नहीं है। वीएस2015 और .NET फ्रेमवर्क 4.6.1, अगर इससे कुछ भी कम करने में मदद मिलती है। –

संबंधित मुद्दे