2009-10-22 2 views
10

다음과 같은 것이 가능한지 궁금합니다. 익명 형식 (문자열, int, decimal, customObject 등)을 허용하는 클래스를 만든 다음 Type을 기반으로 다른 작업을 수행하는 오버로드 된 메서드를 만듭니다. 예형식으로 메서드 오버로드 C#

class TestClass<T> 
{ 
    public void GetName<string>() 
    { 
     //do work knowing that the type is a string  
    } 

    public string GetName<int>() 
    { 
     //do work knowing that the type is an int 

    } 

    public string GetName<int>(int addNumber) 
    { 
     //do work knowing that the type is an int (overloaded)  
    } 

    public string GetName<DateTime>() 
    { 
     //do work knowing that the type is a DateTime 

    } 

    public string GetName<customObject>() 
    { 
     //do work knowing that the type is a customObject type  
    } 

} 

그래서 지금은 GetName 메서드를 호출 할 수 있고, 내가 객체를 초기화 할 때 이미 유형에 전달하기 때문에, 올바른 방법을 찾아 실행됩니다.

TestClass foo = new TestClass<int>(); 

//executes the second method because that's the only one with a "int" type 
foo.GetName(); 

이것이 가능한가요 아니면 단지 꿈꿔야할까요?

답변

12

은 다음과 같이 할 수있다 :이 가능입니다

class TestClass<T> 
{ 
    public string GetName<T>() 
    { 
     Type typeOfT = typeof(T); 
     if(typeOfT == typeof(string)) 
     { 
      //do string stuff 
     } 
    } 
} 

동안, 당신이 가지 제네릭의 목적을 물리 치고 있습니다. 제네릭의 요지는 유형이이 아니기 때 문에 제네릭이 적절하다고 생각하지 않습니다.

0

클래스 확장 방법을 사용하면 효과가 있습니까?

원하는 클래스에 본질적으로 메서드를 추가 할 수 있으며, 같은 방식으로 호출 할 수 있습니다.

사용하여 호출
namespace ExtensionMethods 
{ 
    public static class MyExtensions 
    { 
     public static int GetName(this String str) 
     { 
      ... 
     } 
    } 
} 

는 :

myString.GetName(); 
4

는 "전문화"++ C#으로는 C에있는 방법은 불가능합니다. .NET 제네릭에서 <T>의 일반 클래스 또는 메서드는 T의 가능한 모든 값에 대해 동일해야합니다. 이렇게하면 런타임에서 TestClass < 문자열 > 및 TestClass < List < int와 같은 두 가지 다른 참조 유형을 최적화 할 수 있습니다. > >은 동일한 기계어 코드를 공유합니다. (다른 값 유형은 별도의 시스템 코드를 얻을,하지만 당신은 여전히 ​​전문 수 없습니다.) 내가 찾을

는 때때로이 같은 일반적인 인터페이스 또는 기본 클래스를 만들 수 있습니다 :

abstract class Base<T> { 
    public abstract T GetName(); 
    // any common code goes here that does not require specialization 
} 

을 그리고 유도에 전문성을 수업 :

class IntVersion : Base<int> { 
    public override int GetName() { return 1; } 
    public int GetName(int addNumber) { ... } 
} 
class StringVersion : Base<string> { 
    public override string GetName() { return "foo"; } 
} 
class DateTimeVersion : Base<DateTime> { 
    public override DateTime GetName() { return DateTime.Now; } 
} 
+0

+1 Generics! = Templates – user7116

1

아니요. 불가능합니다. 당신이하려고하는 것은 C++에서 (슬프게도) 가능하지 않은 C++의 템플릿 전문화와 비슷합니다.

당신은 전문 구현을 호출 할

typeof(T) 

에하는 경우/다른 사람 또는 스위치가 필요합니다.

public Foo<T> DoBar<T>() where T : FooBase; 
0

C#을이를 지원하지 않습니다

그러나, 당신은 하나의 클래스 (참고 값) 또는 특정의 base class의 구조체 (값) 또는 서브 클래스과 같이 될 T의 형식을 제약 조건 수 그러한 파견.

>가 메서드 서명의 일부가 아닌 한 메서드 오버로드 (Error'TestClass는 이미 동일한 매개 변수 형식의 'GetName'이라는 멤버를 정의합니다.)를 수행하는 올바른 방법이 아닙니다.당신이 뭘 하려는지

3

C#에서는 전문화가 불가능합니다. C#에서 가장 가까운 것은 다음과 같습니다.

public void Example() { 
    public static void Method<T>(T value) { ... } 
    public static void Method(int value){ ... } 
    public static void Method(string) { ... } 
} 

C# 컴파일러는 일반 메서드보다 비 제너릭 메서드를 선호합니다. 즉, int 매개 변수를 사용하여 호출하면 int 오버로드와 일반적인 오버로드가 바인딩됩니다.

Example.Method(42); // Method(int) 
Example.Method(new Class1()) // Method<T>(T) 

이렇게하면 메서드가 일반적으로 호출 될 때 적용되지 않기 때문에이 문제가 발생합니다. 이 경우 유형에 관계없이 일반 오버로드에 바인딩됩니다.

public void Gotcha<T>(T value) { 
    Example.Method(value); 
} 

Gotcha(42); // Still calls Example.Method<T>() 
0

클래스에서 특정 유형의 작업을 수행해야하는 경우 클래스는 일반적이지 않습니다. 당신은 아마 당신이 처리하고자하는 각각의 유형에 대해 별도의 클래스를 만들어야합니다. 제네릭에 대한 적절한 이유가있는 일부 기능이있는 경우이를 공통 기본 클래스에 넣을 수 있습니다.

예 :

abstract class TestClass<T> 
{ 
    public List<T> Items { get; set; } 

    // other generic (i.e. non type-specific) code 
} 

class IntTestClass : TestClass<int> 
{ 
    public string GetName() 
    { 
     // do work knowing that the type is an int 
    } 

    // other code specific to the int case 
} 

class StringTestClass : TestClass<string> 
{ 
    public string GetName() 
    { 
     // do work knowing that the type is a string 
    } 

    // other code specific to the string case 
} 
0

BFree 트리, 또는 좀 더 가능성이 switch 문 경우 당신은이 작업을 수행 할 수 언급하지만, 어떤 점에서 당신이 닷넷을 그냥 방법을 쓸 수 있으면 좋겠다 및 드리겠습니다으로 특히 시간이 지남에 따라 과부하 라이브러리가 커질 경우이를 파악하십시오. 이 닷넷 꽤 저렴 성능 현명하지만, 반사,이

솔루션 :

using System.Reflection; 
... 

public string DoSomething(object val) 
{ 
    // Force the concrete type 
    var typeArgs = new Type[] { val.GetType() }; 

    // Avoid hard-coding the overloaded method name 
    string methodName = new Func<string, string>(GetName).Method.Name; 

    // Use BindingFlags.NonPublic instead of Public, if protected or private 
    var bindingFlags = BindingFlags.Public | BindingFlags.Instance; 

    var method = this.GetType().GetMethod(
     methodName, bindingFlags, null, typeArgs, null); 

    string s = (string)method.Invoke(this, new object[] { val }); 

    return s; 
} 

당신은 기본적으로 그냥 당신을 위해 switch 문을 가기 위해 반사 프레임 워크를 말하는 것입니다.