2009-10-13 8 views
3

제네릭 형식의 개체에 대한 참조를 전달하는 데 문제가 있습니다. 나는 'Object'를 생성하고 원본보다는 그 참조를 전달하는 방법을 발견했다. 그러나 그것은 나에게 조금은 냄새가 난다. 여기에 더 좋은 방법이 있을까요 아니면 함께 살 필요가 있습니까?제네릭 개체에 대한 참조를 매개 변수로 사용

첫 번째 오류는 이해하지만 두 번째 오류는 알지 못합니다.

public static T Foo<T>(ref T Bar) 
{ 
    T Result; 

    // Next line gives 
    // cannot convert from 'ref T' to 'ref object' 
    Result = (T)ModifyObject (ref Bar); 

    // Next line gives 
    // A ref or out argument must be an assignable variable 
    Result = (T)ModifyObject (ref ((Object)Bar)); 

    // Works 
    Object Tmp = Bar; 
    Result = (T)ModifyObject (ref Tmp)); 

    return Result; 

} 

public static Object DoSomthing(ref Object Obj) { 
    Object Result = Activator.CreateInstance (Obj.GetType()) 
    //... 
} 

DoSomething은 Obj 유형이 변경 될 수있는 재귀를 사용하기 때문에 일반적이지 않습니다. 게시를 통해 더 좋은 옵션이 될 수 있지만 리플렉션을 사용하여 일반적인 버전을 호출하지 않으려 고 노력하고 있었습니까?

+3

정말 참조로 전달해야합니까? DoSomething 내부에서 Obj에게 할당합니까? – Henrik

+0

그리고 Foo에 맞습니까! –

+0

(참조 정보에 대한 자세한 내용은 http://pobox.com/~skeet/csharp/parameters.html을 참조하십시오.) –

답변

5

ref 인수의 유형은 매개 변수의 유형과 일치해야합니다. 여기서 암시 적 변환에 의존 할 수는 없습니다. 에릭 Lippert의이 관련 블로그 게시물이 있습니다

object obj = (object)Bar; 
Result = (T)ModifyObject (ref obj); 

을하지만 방법이 실행 된 후, 유일한 것은 확실하다 : Why do ref and out parameters not allow type variation?

+0

처음 오류가 설명되어있는 동안. 나는 ref 연산자를 적용하기 전에 명시 적으로 객체 (함수와 동일한 유형의 매개 변수)로 캐스팅하는 두 번째를 이해하지 못합니다. –

+1

@Courtney :'ref' 매개 변수는 선언 된 유형의 "변수"가 ** 값이 아닌 **을 기대합니다. 'ref int' 매개 변수에는 42를 전달할 수 없습니다. 캐스트는 변수가 아닌 값에 대해 작동합니다. 당신은 피 호출자에게 ** 객체를 잡기위한 ** 장소 **를 주어야합니다. 예를 들어, 피 호출자가 '문자열'을 넣을 수 있기 때문에이 장소는 'int'변수가 될 수 없습니다. –

+0

나는 지금 Gotcha :) - 그래서 내가 가진 해결책이 그것을 할 수있는 최선의 방법이라는 것을 의미할까요? –

0

두 번째 예를 들어를 먼저 개체 변수에 캐스팅해야합니다 objObject입니다. 그것이 컴파일러가 경고하는 것입니다.

코드 에 약간의 냄새가납니다. 형식 T의 결과를 반환하는 경우 매개 변수를 참조로 전달할 이유가 표시되지 않습니다. 두 번째로, 참조를 기준으로 유형 인스턴스를 전달할 필요가 없습니다. 이 방법은 잘 작동합니다.

public static Object DoSomething(Type objType) { 
    Object Result = Activator.CreateInstance(objType) 
} 

마지막으로 제네릭을 사용하는 경우 모든 캐스팅을 수행 할 이유가 없어야합니다. 즉 입니다. 정확히 일반 매개 변수를 사용하여 클래스를 다양한 유형의 템플릿으로 만듭니다. 당신이 캐스팅하여 새로운 객체를 만들 :

의 Ref 또는 축소 인수가있어 어사 변수

해야합니다 :

3

는 두 번째 오류 메시지가 이미 설명을 포함 (Object) bar 할 수있다 그럼에도 불구하고 동일한 기본 객체를 참조하지만 다른 값입니다. 또한 임시 값입니다. 별개의 변수 이름에 할당하지 않았기 때문입니다. 따라서 참조로 전달하는 것은 의미가 없으며 해당 임시 객체에 대한 변경 사항은 손실됩니다. 따라서 임시 변수는 엄밀히 말하면 rvalues입니다. 할당 할 수 없거나 참조로 전달할 수 없습니다.

이것은 세 번째 코드가 작동하는 이유이기도합니다. 이제 변환 결과를 새로운 이름으로 바인딩 했으므로이 이름을 lvalue로 사용할 수 있습니다. 즉,이 값을 lvalue로 사용하여 변경할 수 있습니다 .

관련 문제