문제

다음이 가능한지 궁금합니다. 익명 유형 (String, int, Decimal, CustomObject 등)을 수락하는 클래스를 만듭니다. 그런 다음 유형을 기반으로 다른 작업을 수행하는 과부하 메소드를 가지고 있습니다. 예시

    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();

이것이 가능합니까 아니면 내가 꿈꾸는가?

도움이 되었습니까?

해결책

당신이하려는 것은 다음과 같이 가능합니다.

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

이건 ~이다 가능하면, 당신은 제네릭의 목적을 물리 치고 있습니다. 제네릭의 요점은 유형의시기입니다 그렇지 않습니다 문제,이 경우 제네릭이 적절하다고 생각하지 않습니다.

다른 팁

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>()

C#에서 "전문화"는 C ++의 방식으로 불가능합니다. .NET 제네릭에서 일반 클래스 또는 방법u003CT> T의 가능한 모든 값에 대해 동일해야합니다. 이렇게하면 런타임이 두 가지 다른 참조 유형 (TestClass)을 최적화 할 수 있습니다.u003Cstring> 그리고 TestClass u003CListu003Cint> >, 동일한 기계 언어 코드를 공유하십시오. (다른 값 유형은 별도의 기계 코드를 얻지 만 여전히 전문화 할 수 없습니다.)

때로는 일반 인터페이스 또는 기본 클래스를 작성하는 데 도움이됩니다.

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; }
}

아니요, 이것은 불가능합니다. 당신이하려는 것은 C#에서는 (슬프게도) C ++의 템플릿 전문화와 유사합니다.

if/else 또는 전환해야합니다

typeof(T)

특수 구현을 호출합니다.

그러나 T 유형을 클래스 (참조 값) 또는 구조물 (값) 또는 특정베이스 클래스의 서브 클래스로 제한 할 수 있습니다.

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

C#은 이러한 파견을 지원하지 않습니다.

그리고 이것은 모든 내부 <>가 메소드 서명의 일부가 아닌 한 메서드 과부하 (Error'TestClass '가 동일한 매개 변수 유형으로'getName이라는 멤버를 이미 정의하는 것)를 수행하는 올바른 방법이 아닙니다.

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

기본적으로 원하는 클래스에 메소드를 추가 한 다음 같은 방식으로 호출 할 수 있습니다.

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int GetName(this String str)
        {
            ...
        }
    }   
}

사용을 사용합니다 :

myString.GetName();

수업에서 유형별 작업을 수행 해야하는 경우 수업이 일반적이지 않습니다. 처리하려는 각 유형에 대해 별도의 클래스를 만들어야 할 것입니다. 일반적인 이유가있는 기능이있는 경우 일반적인 기본 클래스에 넣을 수 있습니다.

An example:

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
}

Bfree가 언급했듯이 IF 트리 또는 스위치 명령문 으로이 작업을 수행 할 수 있지만, 어느 시점에서는 시간이 지남에 따라 과부하 라이브러리를 키우는 경우 방법을 작성하고 .NET을 알아낼 수 있기를 바랍니다. .

.NET에서는 성능이 저렴하지만 반사 솔루션이 있습니다.

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;
}

당신은 기본적으로 반사 프레임 워크를 통해 그 스위치 문을 연주하도록 지시합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top