سؤال
هل هناك طريقة لفرض/الحد من الأنواع التي يتم تمريرها إلى الأوليات? (منطقي, 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
}
أنا أفكر في هذا الحل ، كل على الرغم من العديد من اقترح كنت جزءا من بلدي الاختيار أيضا.
قلقي هو - مع ذلك - هو مضللة المحتملة المطورين باستخدام صفك ؟
هتافات و شكرا.