일반 유형 검사
프리미티브에 전달되는 유형을 강제 / 제한하는 방법이 있습니까? (bool, int, 문자열 등)
이제 where 절을 통해 일반 유형 매개 변수를 유형 또는 인터페이스 구현으로 제한 할 수 있다는 것을 알고 있습니다 . 그러나 이것은 원시 (AFAIK)에 대한 청구서에 맞지 않습니다. 왜냐하면 그들은 모두 공통된 근거를 가지고 있지 않기 때문입니다 ( 누군가가 말하기 전에 객체 를 제외하고 ! : P).
그래서, 내 현재 생각은 내 이빨을 긁고 큰 switch 문을 수행하고 실패시 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 편집
@Jon Limjap-좋은 지적이고, 이미 고려하고있는 것 .. 유형이 값인지 참조 유형인지 판단하는 데 사용할 수있는 일반적인 방법이있을 것입니다 ..
이것은 내가 다루고 싶지 않은 많은 객체를 즉시 제거하는 데 유용 할 수 있습니다 (그러나 Size 와 같이 사용되는 구조체에 대해 걱정할 필요가 있습니다 ) .. 흥미로운 문제가 있습니까? :)
여기있어:
where T : struct
MSDN 에서 가져 왔습니다 .
궁금합니다 .. 확장 메서드를 사용하여 .NET 3.x에서이 작업을 수행 할 수 있습니까? 인터페이스를 만들고 확장 메서드에서 인터페이스를 구현합니다 (약간 뚱뚱한 스위치보다 더 깔끔 할 것입니다). 또한 나중에 경량 사용자 지정 형식으로 확장해야하는 경우 기본 코드를 변경할 필요없이 동일한 인터페이스를 구현할 수도 있습니다.
너희들은 어떻게 생각하니?
슬픈 소식은 내가 Framework 2에서 일하고 있다는 것입니다 !! :디
3 편집
이것은 Jon Limjaps Pointer의 후속작 으로 매우 간단했습니다 .. 너무 간단해서 거의 울고 싶지만 코드가 매력처럼 작동하기 때문에 좋습니다!
그래서 여기에 내가 한 일이 있습니다 (당신은 웃을 것입니다!) :
일반 클래스에 추가 된 코드
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 (직장에서 사용하지 않음) 과 같은 유틸리티 로 선택할 수 있습니다.
이것에 대해 Jon 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
{
}
이건 제대로 된 것 같던데 ..
@Lars가 이미 말한 것 :
//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()
모두 .NET 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
}
A problem here is that you would need to type MyClass<AnyTypeItDoesntMatter>.FromInt32, which is annoying. There isn't a very good way around this if you want to maintain the private-ness of the constructor, but here are a couple of workarounds:
- Create an abstract class
MyClass. MakeMyClass<T>inherit fromMyClassand nest it withinMyClass. Move the static methods toMyClass. This will all the visibility work out, at the cost of having to accessMyClass<T>asMyClass.MyClass<T>. - Use
MyClass<T>as given. Make a static classMyClasswhich calls the static methods inMyClass<T>usingMyClass<AnyTypeItDoesntMatter>(probably using the appropriate type each time, just for giggles). - (Easier, but certainly weird) Make an abstract type
MyClasswhich inherits fromMyClass<AnyTypeItDoesntMatter>. (For concreteness, let's sayMyClass<int>.) Because you can call static methods defined in a base class through the name of a derived class, you can now useMyClass.FromString.
This gives you static checking at the expense of more writing.
If you are happy with dynamic checking, I would use some variation on the TypeCode solution above.
@Rob, Enum's will slip through the TypeValid function as it's TypeCode is Integer. I've updated the function to also check for 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
You can simplify the EnforcePrimitiveType method by using typeof(PrimitiveDataType).IsPrimitive property. Am I missing something?
Use a custom FxCop rule that flags undesirable usage of MyClass<>.
Having a similar challenge, I was wondering how you guys felt about the IConvertible interface. It allows what the requester requires, and you can extend with your own implementations.
Example:
public class MyClass<TKey>
where TKey : IConvertible
{
// class intentionally abbreviated
}
I am thinking about this as a solution, all though many of the suggested was part of my selection also.
My concern is - however - is it misleading for potential developers using your class?
Cheers - and thanks.
참고URL : https://stackoverflow.com/questions/8941/generic-type-checking
'program story' 카테고리의 다른 글
| JavaScript에서 정규식 패턴으로 동적 (변수) 문자열 사용 (0) | 2020.11.04 |
|---|---|
| Java의 기본값 및 초기화 (0) | 2020.11.04 |
| PHP : 괄호 안의 텍스트를 추출하는 가장 좋은 방법은 무엇입니까? (0) | 2020.11.04 |
| 어떤 Lisp를 배워야합니까? (0) | 2020.11.03 |
| mysql에서 선택 (0) | 2020.11.03 |