سؤال

أفترض أن هذا أكثر من رانت عام، ولكن لماذا لا يمكنني الحصول على C # لاستنتاج نوع هويتي؟

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>

و EntityObject المحدد مع GUID كمعرف على النحو التالي:

public Foo : EntityObject<Guid>

ورث من فئة EntityObject المجردة المحددة على النحو التالي:

public abstract class EntityObject<IdT>
{
    public IdT id { get; set; }
}

سيكون استخدام طريقة Get كما يلي:

IRepository repository = new Repository();
var hydratedFoo = repository.Get<Foo>(someGuidId);

تم تحريره لتوفير مزيد من التوضيح.

هل كانت مفيدة؟

المحلول

من الصعب القول أن تعطى أنك تعطى فقط إعلانين، وليس كيف تستخدمها. هل IDT معلمة نوع آخر في مكان ما؟ (لو كان TId, ، من شأنها أن تشير إلى أنها - ولكن حقيقة أنك تستخدم EntityT بالنسبة لمعلمة نوع آخر، مخالفة للاتفاقيات، تشير إلى أنه ربما IdT كذلك ...

الآن، افترض IdT في الواقع Guid في حالتك، كيف يجب أن يعمل المحول البرمجي الذي تقصده Fooب يمكن أن يكون هناك أنواع أخرى مستمدة من EntityObject<Guid>.

باختصار، لم تمنحنا معلومات كافية لإخبار أي شيء بالتأكيد، لكنها تبدو وكأنك تقدم أساسا مطالب غير معقولة على المترجم.

تحرير: حسنا، ها هي تخميني على ما لديك، باستخدام اتفاقيات التسمية العادية:

public interface IRepository
{
    TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>
}

public abstract class EntityObject<TId>
{
    public IdT id { get; set; }
}

public class Foo : EntityObject<Guid> {} 

تريد ان تفعل:

IRepository repository = GetRepositoryFromSomewhere();
Foo foo = repository.Get<Foo>(someGuid);

في حين أن عليك حاليا القيام به:

Foo foo = repository.Get<Foo, Guid>(someGuid);

نعم، المحول البرمجي هو جعله قليل جدا أصعب بالنسبة لك من اللازم. 6 أحرف إضافية كاملة، من أجل الحفاظ على اللغة أبسط وقواعد الاستدلال من النوع أسهل لفهم.

أساس الأساس الاستدلال هو علاقة كل شيء أو لا شيء - إما الكل يتم استنتاج معلمات الكتابة أو لا أحد منهم. هذا يبقيه بسيطا لأنك لا تحتاج إلى العمل التي يتم تحديدها والتي ليست كذلك. هذا جزء من المشكلة، والجزء الآخر هو أنه يمكنك التعبير عن القيود فقط على معلمات النوع للطريقة - لا يمكنك الحصول على:

class Repository<TEntity>
{
    TEntity Get<TId>(TId id) where TEntity : EntityObject<TId>
}

لأن هذا يقيد TEntity, ، ليس TId. وبعد مرة أخرى، هذا النوع من الأشياء يجعل من النوع يستنتج أبسط.

الآن أنت استطاع يحتمل أن يكتب:

Foo foo = repository.Get(someGuid).For<Foo>();

مع مناسب Get الطريقة وواجهة إضافية. أعتقد أنني شخصيا أفضل استخدام Get<Foo, Guid> على أية حال.

نصائح أخرى

إعلان مثل

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>

يتطلب أن IDT هو نوع ملموس. إذا كنت ترغب في تحديد IDT أيضا، فستحتاج إلى استخدامها

public EntityT Get<EntityT, IdT>(IdT id) where EntityT : EntityObject<IdT>

ولكن ربما لا يكون ما تريد.

هذا هو السبب في أنني أتخلى عن أنواع أساسية عامة مع كيانات عامة. لم أستطع معرفة كيفية الحصول على كيانات لي أن يكون لها أنواع رئيسية عامة دون رش اثنين في كل مكان. لقد استقر الآن على مفاتيح عدد صحيح (وهو ما لدي في كل مكان على أي حال) لكنه يشعر بالخطأ.

إذا كانت توقيع طريقتك تبدو وكأنها:

public TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>

سيكون للمترجم لديه شيء للعمل مع ...

ثم اتصل بالاستدعاء مع شيء مثل:

تحرير (كنت مخطئا): المنتج P = الحصول على (ID)؛

Product p = Get<Product, Guid>(id);

مسمر جون هذه الإجابة مع منشوره أعلى لذلك سأصبح وأعاد الزحف في ثقبي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top