2012-04-17 6 views
0

최근 나 자신이 점점 더 많은 것들을 참조로 전달하는 습관을 갖게된다는 것을 알게되었습니다. 저는 항상 심판을 통과하는 것이 '보통'나쁜 생각인데, 당신의 물건에 영향을 미칠 수있는 것을 추적하는 것이 더 까다롭기 때문에 질문을 게시하고 싶었습니다 : '참조로 전달할 때의 단점은 무엇입니까? ? '참조로 전달할 때의 단점은 무엇입니까?

최근에 참조로 전달한 예제는 viewstate 내에 지연 인스턴스화 된 개체입니다. 코드 숨김 내에서 공용 속성이있는 개인 필드가 있는데 이는 도우미 메서드를 사용합니다.

ASPX 코드 숨김

/// <summary> 
/// Private field member for MyObject 
/// </summary> 
private Foobar _myObject = null; 

/// <summary> 
/// Gets or sets the current object 
/// </summary> 
public Foobar MyObject 
{ 
    get 
    { 
     return this.ViewState.GetValue("MyObject", new Foobar(), ref this._myObject); 
    } 
    set 
    { 
     this.ViewState.SetValue("MyObject", value, ref this._myObject); 
    } 
} 

이이 클래스 내의 필드와 게으른 인스턴스화하는 물체로부터 반복적 인 if 할당 검사를 많이 대체하는 것을 목표로 다음과 같이 구현하는 현재입니다. 예를 들어 도우미 클래스가 없다면 비슷한 것입니다.

/// <summary> 
/// Private field member for MyObject 
/// </summary> 
private Foobar _myObject = null; 

/// <summary> 
/// Gets or sets the current object 
/// </summary> 
public Foobar MyObject 
{ 
    get 
    { 
     if (this._myObject != null) 
     { 
      return this._myObject; 
     } 

     var viewStateValue = this.ViewState["MyObject"]; 
     if (viewStateValue == null || !(viewStateValue is Foobar)) 
     { 
      this.ViewState["MyObject"] = new Foobar(); 
     } 

     return this._myObject = (Foobar)this.ViewState["MyObject"]; 
    } 
    set 
    { 
     this._myObject = value; 
     this.ViewState["MyObject"] = value; 
    } 
} 

코드 스 니펫은 모두 동일합니다. 첫 번째 방법은 모든 것을 중앙 집중화하는 것인데, 좋은 일이지만 참조로 전달하는 것입니다.이 경우에는 좋은 아이디어가 아닌 것인지 잘 모르겠습니다.

모든 조언 및/또는 경험을 높이 평가합니다.

편집 GetValueSetValue은의 ViewState에 확장 방법이 있습니다. 코드는 아래에 제공됩니다.

/// <summary> 
/// Gets a value from the current view state, if the type is correct and present 
/// </summary> 
public static T GetValue<T>(this StateBag source, string key, T @default) 
{ 
    // check if the view state object exists, and is of the correct type 
    object value = source[key]; 
    if (value == null || !(value is T)) 
    { 
     return @default; 
    } 

    // return the object from the view state 
    return (T)source[key]; 
} 

/// <summary> 
/// Sets the key value within the view state 
/// </summary> 
public static void SetValue<T>(this StateBag source, string key, T value) 
{ 
    source[key] = value; 
} 

/// <summary> 
/// Gets a value from the reference field helper, or the current view state, if the type is correct and present 
/// </summary> 
/// <returns>Returns a strongly typed session object, or default value</returns> 
public static T GetValue<T>(this StateBag source, string key, T @default, ref T fieldHelper) 
{ 
    return fieldHelper != null ? fieldHelper : fieldHelper = source.GetValue(key, @default); 
} 

/// <summary> 
/// Sets the key value within the view state and the field helper 
/// </summary> 
/// <param name="value">The value</param> 
public static void SetValue<T>(this StateBag source, string key, T value, ref T fieldHelper) 
{ 
    source[key] = value; 
    fieldHelper = value; 
} 
+0

현재 'ViewState.GetValue (...);'에 체크와 게으른 인스턴스가 없다면? 왜'Foobar' 클래스에 제네릭 메소드를 가질 수 없습니까? – Default

+2

조금 이상해 보입니다. 왜 당신은'_myObject'에 한 번,'this.ViewState [ "MyObject"]'에 한 번 같은 객체를 두 번 저장하고 싶습니까? 첫 번째'get'은 리턴을 전혀 가지고 있지 않으며, 당신이 그것을 사용하든 안하든 항상 새로운 객체를 인스턴스화합니다. – martinstoeckli

+0

가능한 복제본 : http://stackoverflow.com/questions/570471/whats-so-bad-about-ref-parameters – Default

답변

1

그냥 몇 가지 옵션에서 차이가 없습니다 를 사용하는 경우 클래스와 같은

복잡한 객체는에 allways 참조에 의해 전달된다.

당신은 적은 코드의 라인없이 심판과 동일한 결과를 얻을 수있는 경우 또는

get 
{ 
    if (this._myObject == null) 
     this._myObject = this.ViewState.GetValue<Foobar>("MyObject", new Foobar()); 
    return this._myObject; 
} 

ViewState.GetValue 반환의 ViewState에서 객체를 설정하고 반환 기본 (새 FOOBAR()). 나는 이것이 게으른 프로퍼티 초기화 (또는 당신은 .Net 4.0에서 Lazy를 사용할 수도있다)를하는 꽤 표준적인 방법이라고 생각한다. 당신은 한 줄이 응축 할 수 있습니다

return this._myObject = this._myObject ?? this.ViewState.GetValue("MyObject", new Foobar()) 

을 대신 당신이 좋아하는 개인 필드를 설정 작업 전달할 수 심판에 의해 전달하는 :

this.ViewState.GetValue("MyObject", new Foobar(), newValue => this._myObject = newValue); 

나는 이런 식의 ViewState를 생각하고는 foobar 덜 결합됩니다 .

또한 새로운 Foorbar()를 기본값으로 생성하는 대신() => Foorbar() (또는 Lazy)를 전달할 수 있으므로 필요한 경우 한 번만 생성됩니다.

적어도 귀하의 경우에는 ref를 사용해야 할 충분한 이유가 없습니다.

+0

'Action '을 사용하는 것은'Controls'와'ViewState'의 연결을 해제하는 환상적인 답입니다. 고맙습니다. :) – Richard

+0

또한, 앞으로'Action '이'ref'를 사용하는 것보다 더 적절한 방법이라고 생각합니다. 다시 한 번 감사드립니다. – Richard

0

참조에 의한 강제 전달은 string 또는 int와 같은 프리미티브 개체에서만 유용합니다.

ref를 사용하지 않으면 함수의 값만 전달하고 메모리의 다른 개체는 가리키게됩니다. 당신이 "REF"또는하지 ...이 경우에 고려해야 할 모든 ;-)

+3

''ref '를 사용하면 클래스와 같은 복합 객체가 참조로 전달됩니다 ... 전혀 차이가 없습니다 ;-) 이것은 ... diff를 만듭니다. 객체를 ref로 전달하면 참조를 변경할 수 있어야합니다 (즉, 다른 객체를 참조하도록 만들 수 있습니다). 그러나 다른 경우에는 객체의 멤버 값만 변경할 수 있습니다 .. – dotNETbeginner

+0

"원시 유형". 그러나 "값 유형"을 의미하면 '문자열'이 아닙니다. – svick

1

Dave 덕분에 Lazy <> 클래스를 사용해 볼 수 없습니다 .--).

public class Foobar 
{ 
} 

public class ViewState 
{ 
    private readonly Lazy<Foobar> _foobar = new Lazy<Foobar>(); 

    public Foobar LazyFoobar 
    { 
    get { return _foobar.Value; } 
    } 
} 

// Gets or creates the foobar 
Foobar lazyFoobar = this.ViewState.LazyFoobar; 

다음과 같은 장점이있는 것 ViewState에 대한 클래스를 구현 :

  1. 그것은 안전
  2. 게으른 로딩을 입력 것은 캐시 된 객체가 필요 (보다 안정적) 없습니다
  3. 을 쉽게 통합 할 수
  4. 코드를 읽을 수 있습니다
  5. 코드가 빠릅니다 (유형 변환 없음)

원래 질문에 대답하려면 : 참조를 전달하면 다른 코드가 객체를 바꿀 수 있습니다. 우리는 호출 된 함수를 신뢰해야하며이 참조를 다른 객체로 전달하지 않으며 나중에 언제든지 원래 객체를 대체해야합니다.

관련 문제