C ++ और C # दोनों एक नए प्रकार का निर्माण करने के लिए आसान तरीके याद कर रहे हैं जो कि एक टाइपिंग के प्रकार के समान है। मुझे लगता है कि टाइप-सेफ प्रोग्रामिंग के लिए इस तरह के 'टाइपफेड' पूरी तरह से आवश्यक हैं और इसका वास्तविक शर्म की बात यह नहीं है कि उनके पास बिल्ट-इन नहीं है। के बीच अंतर void f(string connectionID, string username)
करने के लिए void f(ConID connectionID, UserName username)
स्पष्ट है ...
(आप BOOST_STRONG_TYPEDEF में बढ़ावा देने के साथ C ++ में कुछ समान हासिल कर सकते हैं)
यह उत्तराधिकार का उपयोग करने के लिए आकर्षक हो सकता है लेकिन इसकी कुछ प्रमुख सीमाएँ हैं:
- यह आदिम प्रकारों के लिए काम नहीं करेगा
- व्युत्पन्न प्रकार को अभी भी मूल प्रकार में डाला जा सकता है, अर्थात हम इसे अपने मूल प्रकार को प्राप्त करने वाले फ़ंक्शन में भेज सकते हैं, यह पूरे उद्देश्य को हरा देता है
- हम सील की गई कक्षाओं से नहीं निकल सकते (और कई .NET क्लास सील हैं)
C # में एक समान चीज़ को प्राप्त करने का एकमात्र तरीका एक नए वर्ग में हमारे प्रकार की रचना है:
Class SomeType {
public void Method() { .. }
}
sealed Class SomeTypeTypeDef {
public SomeTypeTypeDef(SomeType composed) { this.Composed = composed; }
private SomeType Composed { get; }
public override string ToString() => Composed.ToString();
public override int GetHashCode() => HashCode.Combine(Composed);
public override bool Equals(object obj) => obj is TDerived o && Composed.Equals(o.Composed);
public bool Equals(SomeTypeTypeDefo) => object.Equals(this, o);
// proxy the methods we want
public void Method() => Composed.Method();
}
जबकि यह काम करेगा यह सिर्फ एक टाइपराइफ के लिए बहुत ही क्रिया है। इसके अलावा, हमें सीरीज़िंग (यानी जोंस) के साथ एक समस्या है क्योंकि हम क्लास को उसकी कंपोज़्ड प्रॉपर्टी के ज़रिए सिलसिलेवार करना चाहते हैं।
नीचे एक सहायक वर्ग है जो इसे बहुत सरल बनाने के लिए "उत्सुकता से पुनरावर्ती टेम्पलेट पैटर्न" का उपयोग करता है:
namespace Typedef {
[JsonConverter(typeof(JsonCompositionConverter))]
public abstract class Composer<TDerived, T> : IEquatable<TDerived> where TDerived : Composer<TDerived, T> {
protected Composer(T composed) { this.Composed = composed; }
protected Composer(TDerived d) { this.Composed = d.Composed; }
protected T Composed { get; }
public override string ToString() => Composed.ToString();
public override int GetHashCode() => HashCode.Combine(Composed);
public override bool Equals(object obj) => obj is Composer<TDerived, T> o && Composed.Equals(o.Composed);
public bool Equals(TDerived o) => object.Equals(this, o);
}
class JsonCompositionConverter : JsonConverter {
static FieldInfo GetCompositorField(Type t) {
var fields = t.BaseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
if (fields.Length!=1) throw new JsonSerializationException();
return fields[0];
}
public override bool CanConvert(Type t) {
var fields = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
return fields.Length == 1;
}
// assumes Compositor<T> has either a constructor accepting T or an empty constructor
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
while (reader.TokenType == JsonToken.Comment && reader.Read()) { };
if (reader.TokenType == JsonToken.Null) return null;
var compositorField = GetCompositorField(objectType);
var compositorType = compositorField.FieldType;
var compositorValue = serializer.Deserialize(reader, compositorType);
var ctorT = objectType.GetConstructor(new Type[] { compositorType });
if (!(ctorT is null)) return Activator.CreateInstance(objectType, compositorValue);
var ctorEmpty = objectType.GetConstructor(new Type[] { });
if (ctorEmpty is null) throw new JsonSerializationException();
var res = Activator.CreateInstance(objectType);
compositorField.SetValue(res, compositorValue);
return res;
}
public override void WriteJson(JsonWriter writer, object o, JsonSerializer serializer) {
var compositorField = GetCompositorField(o.GetType());
var value = compositorField.GetValue(o);
serializer.Serialize(writer, value);
}
}
}
संगीतकार के साथ उपरोक्त वर्ग बस बन जाता है:
sealed Class SomeTypeTypeDef : Composer<SomeTypeTypeDef, SomeType> {
public SomeTypeTypeDef(SomeType composed) : base(composed) {}
// proxy the methods we want
public void Method() => Composed.Method();
}
और इसके अलावा SomeTypeTypeDef
वसीयत में जोसन उसी तरह से धारावाहिक करेगा SomeType
।
उम्मीद है की यह मदद करेगा !