সি ++ এবং সি # উভয়ই একটি নতুন টাইপ তৈরির সহজ উপায় অনুপস্থিত যা একটি বিদ্যমান ধরণের মতো শব্দার্থগতভাবে অভিন্ন। টাইপ-সেফ প্রোগ্রামিংয়ের জন্য আমি এই জাতীয় 'টাইপিডেফস' সম্পূর্ণরূপে অপরিহার্য পাই এবং এটির সত্যিকারের লজ্জাজনক সি # তাদের অন্তর্নির্মিত নেই। মধ্যে পার্থক্য void f(string connectionID, string username)
করার জন্য void f(ConID connectionID, UserName username)
সুস্পষ্ট ...
(আপনি BOOST_STRONG_TYPEDEF এ উন্নীত করে সি ++ তে অনুরূপ কিছু অর্জন করতে পারেন)
উত্তরাধিকার ব্যবহারে এটি লোভনীয় হতে পারে তবে এর কিছু বড় সীমাবদ্ধতা রয়েছে:
- এটি আদিম ধরণের জন্য কাজ করবে না
- উদ্ভূত প্রকারটি এখনও মূল ধরণে কাস্ট করা যেতে পারে, অর্থাত আমরা এটি আমাদের মূল ধরণ প্রাপ্ত কোনও ফাংশনে প্রেরণ করতে পারি, এটি পুরো উদ্দেশ্যকে পরাস্ত করে
- আমরা সিল করা ক্লাস থেকে উদ্ভব করতে পারি না (এবং উদাহরণস্বরূপ অনেক। নেট ক্লাস সিল করা হয়)
সি # তে একই জিনিস অর্জনের একমাত্র উপায় হ'ল আমাদের ধরণের নতুন ক্লাসে রচনা করে:
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
।
আশাকরি এটা সাহায্য করবে !