سؤال

هل هناك طريقة لفرض/الحد من الأنواع التي يتم تمريرها إلى الأوليات? (منطقي, int, string, الخ.)

الآن, وأنا أعلم أنك يمكن أن تحد من نوع عام المعلمة إلى نوع أو واجهة تنفيذ طريق حيث البند.ولكن هذا لا تناسب مشروع القانون الأوليات (AFAIK) لأنها لا تملك أرضية مشتركة (وبصرف النظر عن وجوه قبل أن يقول شخص ما!:P).

حتى الأفكار الحالية هي مجرد حصى أسناني و لا كبير التبديل بيان رمي ArgumentException على الفشل..


تعديل 1:

فقط للتوضيح:

رمز التعريف ينبغي أن يكون مثل:

public class MyClass<GenericType> ....

واللحظة:

MyClass<bool> = new MyClass<bool>(); // Legal
MyClass<string> = new MyClass<string>(); // Legal
MyClass<DataSet> = new MyClass<DataSet>(); // Illegal
MyClass<RobsFunkyHat> = new MyClass<RobsFunkyHat>(); // Illegal (but looks awesome!)

تحرير 2

@جون Limjap - نقطة جيدة و ما كنت تدرس بالفعل..أنا متأكد من أن هناك طريقة عامة التي يمكن استخدامها لتحديد ما إذا كان النوع من قيمة أو نوع مرجع..

هذا يمكن أن يكون مفيدا في الفور إزالة الكثير من الكائنات لا أريد أن التعامل مع (ولكن بعد ذلك تحتاج للقلق حول البنيات التي تستخدم مثل حجم )..مشكلة مثيرة للاهتمام لا ؟ :)

هنا هو:

where T : struct

مأخوذة من MSDN.


أنا الغريب..يمكن أن يكون هذا القيام به .صافي 3.x باستخدام امتداد الطرق ؟ إنشاء واجهة وتنفيذ واجهة في طرق الإرشاد (الذي ربما يكون أنظف من الدهون قليلا التبديل).بالإضافة إلى ذلك إذا كنت تحتاج بعد ذلك إلى وقت لاحق تمتد إلى أي خفيف الوزن مخصص أنواع ، يمكن أيضا تنفيذ نفس واجهة مع أي تغييرات مطلوبة على قاعدة رمز.

ما رأيكم يا رفاق ؟

الخبر المحزن هو أنا أعمل في إطار 2!!:D


تحرير 3

هذه كانت بسيطة جدا وبعد يوم من جون Limjaps المؤشر..بسيطة جدا أنا كنت على وشك البكاء, لكنه عظيم لأنه رمز تعمل مثل السحر!

حتى هنا هو ما فعلته (عليك أن تضحك!):

إضافة رمز إلى فئة عامة

bool TypeValid()
{
    // Get the TypeCode from the Primitive Type
    TypeCode code = Type.GetTypeCode(typeof(PrimitiveDataType));

    // All of the TypeCode Enumeration refer Primitive Types
    // with the exception of Object and Empty (Null).
    // Since I am willing to allow Null Types (at this time)
    // all we need to check for is Object!
    switch (code)
    {
        case TypeCode.Object:
            return false;
        default:
            return true;
    }
}

ثم القليل من المساعدة طريقة للتحقق من نوع رمي استثناء ،

private void EnforcePrimitiveType()
{
    if (!TypeValid())
        throw new InvalidOperationException(
            "Unable to Instantiate SimpleMetadata based on the Generic Type of '" + typeof(PrimitiveDataType).Name + 
            "' - this Class is Designed to Work with Primitive Data Types Only.");
}

كل ذلك يحتاج إلى القيام به هو الاتصال EnforcePrimitiveType() في الطبقات المنشئات.المهمة!:-)

فقط الجانب السلبي واحد فقط يطرح استثناء في وقت التشغيل (الواضح) بدلا من وقت التصميم..ولكن هذا ليس صفقة كبيرة و يمكن أن تكون التقطت مع المرافق مثل FxCop (والتي لا تستخدم في العمل).

شكر خاص إلى جون Limjap على هذا واحد!

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

المحلول

الأوليات تظهر أن تكون محددة في TypeCode التعداد:

ربما هناك طريقة لمعرفة ما إذا كان كائن يحتوي على TypeCode enum دون أن يلقي ذلك إلى كائن معين أو الاتصال GetType() أو typeof()?

التحديث كان تحت ناظري.نموذج التعليمات البرمجية هناك يظهر هذا:

static void WriteObjectInfo(object testObject)
{
    TypeCode    typeCode = Type.GetTypeCode( testObject.GetType() );

    switch( typeCode )
    {
        case TypeCode.Boolean:
            Console.WriteLine("Boolean: {0}", testObject);
            break;

        case TypeCode.Double:
            Console.WriteLine("Double: {0}", testObject);
            break;

        default:
            Console.WriteLine("{0}: {1}", typeCode.ToString(), testObject);
            break;
        }
    }
}

انها لا تزال قبيحة التبديل.لكنه مكان جيد للبدء!

نصائح أخرى

public class Class1<GenericType> where GenericType : struct
{
}

يبدو هذا أحد للقيام بهذه المهمة..

كثيرا ما @لارس قلت:

//Force T to be a value (primitive) type.
public class Class1<T> where T: struct

//Force T to be a reference type.
public class Class1<T> where T: class

//Force T to be a parameterless constructor.
public class Class1<T> where T: new()

كل عمل في .صافي 2 و 3 و 3.5.

إذا كنت يمكن أن يتسامح مع استخدام أساليب المصنع (بدلا من منشئات MyClass طلبت) يمكنك دائما أن تفعل شيئا مثل هذا:

class MyClass<T>
{
  private readonly T _value;

  private MyClass(T value) { _value = value; }

  public static MyClass<int> FromInt32(int value) { return new MyClass<int>(value); }
  public static MyClass<string> FromString(string value) { return new MyClass<string>(value); }
  // etc for all the primitive types, or whatever other fixed set of types you are concerned about
}

المشكلة هنا هو أن كنت بحاجة إلى نوع MyClass<AnyTypeItDoesntMatter>.FromInt32, الذي هو مزعج.ليس هناك طريقة جيدة جدا حول هذا إذا كنت ترغب في الحفاظ على الخاص نيس من منشئ, ولكن هنا بعض الحلول:

  • إنشاء فئة مجردة MyClass.جعل MyClass<T> ترث من MyClass و عش في حدود MyClass.نقل أساليب ثابتة إلى MyClass.وجميع هذه الرؤية ، على بعد الوصول MyClass<T> كما MyClass.MyClass<T>.
  • استخدام MyClass<T> كما هو محدد.جعل فئة ثابتة MyClass الذي يدعو أساليب ثابتة في MyClass<T> باستخدام MyClass<AnyTypeItDoesntMatter> (ربما باستخدام النوع المناسب في كل مرة ، لمجرد الضحك).
  • (أسهل, ولكن بالتأكيد غريب) جعل مجردة نوع MyClass الذي يرث من MyClass<AnyTypeItDoesntMatter>.(على والملموس ، دعونا نقول MyClass<int>.) لأنه يمكنك استدعاء أساليب ثابتة محددة في الفئة الأساسية من خلال اسم فئة مشتقة ، يمكنك الآن استخدام MyClass.FromString.

هذا يعطيك ثابت التحقق على حساب مزيد من الكتابة.

إذا كنت سعيدا مع ديناميكية التحقق, وأود أن استخدام بعض الاختلاف على TypeCode الحل أعلاه.

@روب ، Enum'ق سوف تنزلق من خلال TypeValid وظيفة كما TypeCode هو Integer.لقد تحديث وظيفة أيضا في التحقق Enum.

Private Function TypeValid() As Boolean
    Dim g As Type = GetType(T)
    Dim code As TypeCode = Type.GetTypeCode(g)

    ' All of the TypeCode Enumeration refer Primitive Types
    ' with the exception of Object and Empty (Nothing).
    ' Note: must also catch Enum as its type is Integer.
    Select Case code
        Case TypeCode.Object
            Return False
        Case Else
            ' Enum's TypeCode is Integer, so check BaseType
            If g.BaseType Is GetType(System.Enum) Then
                Return False
            Else
                Return True
            End If
    End Select
End Function

يمكنك تبسيط EnforcePrimitiveType طريقة باستخدام typeof(PrimitiveDataType).IsPrimitive مكان الإقامة.أنا في عداد المفقودين شيئا ؟

استخدام مخصص FxCop القاعدة التي أعلام غير مرغوب فيه استخدام MyClass<>.

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

على سبيل المثال:

    public class MyClass<TKey>
    where TKey : IConvertible
{
    // class intentionally abbreviated
}

أنا أفكر في هذا الحل ، كل على الرغم من العديد من اقترح كنت جزءا من بلدي الاختيار أيضا.

قلقي هو - مع ذلك - هو مضللة المحتملة المطورين باستخدام صفك ؟

هتافات و شكرا.

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