문제

좋은 방법을 어떻게 선택할 수 있습니까 (아래 예제에 작동하지 않는 2 개의 차이점을 표시합니다). IF가있는 유형 객체의 변수 대신 사용 중이고 작업을 수행하는 것이지만 객체와 권투/복싱을 사용하지 않으려 고 노력하고 있습니다. 그래서 나는 Generic이 일을 할 수 있다고 생각했지만 여기에 갇혀 있습니다.

다음은 내 질문을 설명하는 작은 코드 스 니펫입니다.

class Program
{
    static void Main(string[] args)
    {
        Parser p = new Parser();
        ObjectType1 o1 = new ObjectType1();
        p.execute(o1);
        Console.Read();
    }
}

class Parser
{
    public T execute<T>(T obj)
    {
        /*
        if (obj is ObjectType1)
            this.action((ObjectType1)obj);
        else if (obj is ObjectType2)
            this.action((ObjectType2)obj);
        */
        this.action(obj);
        return obj;
    }

    private void action(ObjectType1 objectType1)
    {
        Console.WriteLine("1");
    }

    private void action(ObjectType2 objectType2)
    {
        Console.WriteLine("2");
    }
}


class ObjectType1
{
}

class ObjectType2
{
}

업데이트

인터페이스와 클래스를 원하지 않습니다. 죄송합니다. 나는 그것이 질문의 목표가 아니라는 것을 알았습니다.

(ObjectType) OBJ로 캐스팅하는 것은 작동하지 않지만 그렇다면 :

        if (obj is ObjectType1)
            this.action(obj as ObjectType1);
        else if (obj is ObjectType2)
            this.action(obj as ObjectType1);

작동합니다 ... 왜?

그리고 ...이 메소드는 인터페이스에서 나온 것이기 때문에 모든 유형의 실행 메소드에 대해 과부하 할 수는 없습니다. 이것이이 방법에서 모두를 호출 해야하는 이유입니다.

도움이 되었습니까?

해결책

아니, 당신은 이것을 할 수 없습니다. 제네릭은 C ++ 템플릿처럼 작동하지 않습니다. 제네릭 방법은 한 번만 컴파일됩니다. 컴파일러가 오버로드 해상도에 사용할 수있는 유일한 정보는 코드가 사용하는 코드가 사용하는 것과 상관없이 일반 방법 내에서 알고있는 정보입니다.

이것을 보여주는 예로, 여기에 당신이 그것을 기대하는 방법이 작동하지 않는 약간의 코드가 있습니다.

using System;

class Test
{    
    static void Main()
    {
        string x = "hello";
        string y = string.Copy(x);

        Console.WriteLine(x==y); // Overload used
        Compare(x, y);
    }

    static void Compare<T>(T x, T y) where T : class
    {
        Console.WriteLine(x == y); // Reference comparison
    }
}

당신이하고 싶은 일에 대해 더 많이 모르고 진행하는 가장 좋은 방법은 말하기 어렵습니다.

다른 팁

인터페이스를 고려해 보셨습니까?

interface IAction
{
   void action();
}

class ObjectType1 : IAction
{
   void action() {
      Console.WriteLine("1");
   }
}

class ObjectType2 : IAction
{
    void action() {
      Console.WriteLine("2");
    }
}

class Parser
{
   public IAction execute(IAction obj)
   {
      obj.action();
      return obj;
   }
}

OP에 의해 편집 :

이 솔루션은이 인터페이스를 갖도록 모든 비즈니스 로직 객체를 변경해야합니다. 이것은 실제로 내 상황에서해야 할 일이 아닙니다. 그리고 다른 상황에서는 항상 비즈니스와 관련이없는 인터페이스가없는 깨끗한 비즈니스 객체를 갖는 것을 선호합니다. 내 질문에서, 나는 그것을 달성하기 위해 일반/객체/대표 방법과 더 관련이있는 솔루션을 원합니다. thx 당신. 이 답변은 받아 들여지지 않습니다.

클래스 파서에는 객체 유형에 따라 실행 방법에 의해 호출되는 많은 개인 메소드가 있습니다. 좋은 방법으로 리디렉션해야합니다.

컴파일러 가이 작업을 수행합니다. 오버로드 만 사용하십시오.

class Parser
{
    public ObjectType1 action(ObjectType1 objectType1)
    {
        Console.WriteLine("1");
        return objectType1;
    }
    public ObjectType2 action(ObjectType2 objectType2)
    {
        Console.WriteLine("2");
        return objectType2;
    }
}

class ObjectType1 { }
struct ObjectType2 { }

그런 다음 다음과 같이 호출됩니다.

Parser p = new Parser();
p.action(new ObjectType1());
p.action(new ObjectType2());

권투/개봉이 없으며 적절한 메소드가 호출됩니다.

나는 그것을 시도하지 않았지만 이것을 할 수 있습니까?

public T execute<T>(T obj)
{
    this.action((T)obj);
    return obj;
}

(의견에 따르면 작동하지 않음)

또는

public T execute<T>(T obj)
{
    this.action(obj as T);
    return obj;
}

(의견에 따르면, 작품)

나는 당신이 권투/무 복원에 걱정하고 있다는 것을 알고 있으므로 여기에는 valuetype이있을 수 있습니다.

public T execute<T>(T obj)   
{        
    this.action(obj);
    return obj;
}

행동이 OBJ를 수정하고 있다고 가정하고 또한 이 수정은 발신자에게 중요합니다 (이것이 값을 발신자에게 돌려주는 이유입니다). 이 코드에는 불쾌한 패스 값 결함이 있습니다.

이 코드를 고려하십시오.

    public int execute(int obj)   
    {        
        this.action(obj);
        return obj;
    }

    public void action(int obj)
    {
        obj = obj + 1;
    }

이런 식으로 호출됩니다.

int x = p.execute(1);

X는 1, 2가 아닙니다.

제네릭은 컴파일 타임에서 발생합니다. 동일한 코드를 다른 유형에 적용하려는 경우 가장 잘 사용됩니다. 동적이지 않으므로 입력 유형에 따라 메소드간에 전환하는 데 도움이되지 않습니다.

David B의 답장에서와 같이 과부하가 해결되지만 컴파일 시간 동안 발생합니다.

업데이트의 코드도 같은 작업을 수행합니다. 캐스트 (유형을주의 깊게 확인한 후)를 캐스트 한 다음 과부하를 사용하여 메소드를 해결합니다.

런타임 입력을 기반으로 메소드를 전환하고 싶다고 생각합니다.

반사를 사용하면 더 역동적 인 동작을 얻을 수 있습니다.

        public object execute(object obj) 
        {
            MethodInfo m = typeof(Parser).GetMethod(
                "action", 
                BindingFlags.Instance | BindingFlags.NonPublic, 
                null, 
                new Type[] { obj.GetType() }, 
                null);
            m.Invoke(this, new object[] { obj });
            return obj; 
        } 

아마도 약간 취약하지만 예에서는 작동합니다.

iirc 당신은 이것을 허용하기 위해 "Where"조항을 사용할 수 있습니다.

public T execute<T>(T obj) where : /* somthing */
{
}

나는 항상 내 자신을 구글에해야한다.

편집 : 몇 가지 의견을 읽습니다. 유형 특정 코드를 호출하는 것은 조언하지 않습니다. 오히려 그 코드를 가상 함수에 넣고 호출하십시오. 통화 서명이 길어질 수 있지만 그것이 자동 완료된 것입니다.

Man Page를 찾는 것에 대한 Koodos to Joshua.ewer

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