2012-05-23 2 views
3

나는 하나의 부모로부터 유래 된 많은 개체 군을 가지고 있습니다. 객체는 모두 수정되었는지 알 수있는 방법을 알고 있지만 객체의 새 인스턴스가 이미 메모리에있는 인스턴스와 비교하여 수정되었는지 확인할 수 있어야합니다 (다른 사용자가 데이터베이스를 업데이트했는지 확인하기 위해 테스트하기 . 개체를 편집하는 동안)추상 함수 및 데이터 유형 -이를 수행하는 우아한 방법이 있습니까?

결과는 모든 자식 클래스는 동일한 방법을 포함한다는 것이다 :

public new bool Changed() 
{ 
    return Changed(this); 
} 

이 정말 내 밥통에 스틱을하지만 실제 작업으로 주위에 방법을 볼 수 없습니다 클래스와 동일한 유형의 매개 변수를 취하는 함수에 의해 완료되어야합니다. —에 있으므로 가상 일 수 없습니다. (물론, 부모를 가져 와서 매번 캐스팅하도록 정의 할 수는 있지만, 비교 함수가 올바른 객체가 아닌 트리의 객체를 받아들이게하고, 각 인스턴스의 가드 코드가 필요합니다.

물론이 작동하지만 추한 코드를 싫어합니다.

업데이트 : Changed 함수의 경우 각 개체는로드 될 때 해당 상태의 복사본을 유지합니다.

+0

아마도 당신은 당신의'Changed()'를 좀 더 상세하게 설명 할 수 있습니다. 내 예제를 조정할 수있다. – skarmats

+0

'Changed (SomeDerivedType o)'가 각각의 파생 클래스에 구현되어 있는가? 기본 클래스와 파생 클래스의 예제가있는 몇 줄은 정말 도움이 될 것입니다 :-) 나는 밤이라고 부를 것입니다. – skarmats

+0

@skarmats : 당신은 각 파생 클래스가 Changed (<자신의 타입> o). 각 필드는 자신의 필드를 검사하고 부모 필드를 확인하기 위해 기준을 호출합니다. –

답변

3

만큼 당신의 기본 클래스 abstract 한,이 같은 것을 수행 할 수 있습니다

abstract class Base 
{ 
    public abstract bool Changed<T>(T obj) where T : Base; 

    public bool Changed() 
    { 
     return Changed(this); 
    } 
} 

class Subclass : Base 
{ 
    public override bool Changed<Subclass>(Subclass obj) 
    { 
     // Do stuff here 
    } 
} 
+0

It * Look * * 내가 좋아하는 것을 좋아하지만 컴파일되지 않는다. 무슨 일이 일어나고 있는지 모르겠지만 매개 변수에는 부모 클래스의 필드 만 포함되어 있습니다.보고 싶은 현재 클래스의 필드는 포함되어 있지 않습니다. –

+0

내가 바꿀 수있는 유일한 것은 T가 변경되도록 변경하는 것입니다. 나는 당신이 언제나 클래스 외부에 대한베이스 변경을 호출하기를 원할 것이라고 생각한다. – user957902

+0

방금 ​​테스트 케이스를 시도하여 동일한 결과를 얻었습니다. Base에서 파생 된 Clases에 대한 제약 조건이 생기면이 메서드는 Base의 멤버 만 볼 수 있습니다. – user957902

2

기본 구조는 : 그것의 단점 (readiblity)을 가지고 있지만

public abstract class Base<T> where T : Base<T> 
{ 
    public T Original { get; private set; } 

    public abstract bool Changed(T o); 

    public bool Changed() 
    { 
     return this.Changed(Original); 
    } 
} 

public class DerivedA : Base<DerivedA> 
{ 
    public override bool Changed(DerivedA o) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class DerivedB : Base<DerivedB> 
{ 
    public override bool Changed(DerivedB o) 
    { 
     throw new NotImplementedException(); 
    } 
} 

,이 수를 귀하의 문제는 고전적인 동물/개/고양이의 의미에서 유형 보호가 아니라 코드 공유이므로이 경우 올바른 선택입니다.

public class DerivedC : DerivedB 
{ 
} 
new DerivedB().Changed(new DerivedC()); // compiles 

당신이 DerivedB을 밀봉 수 :

이 시나리오를 방지합니다.

또는 당신은 (나는이 수준보다 확실히 더이 추천하지 않습니다.) 막무가내를 계속할 수 :

public abstract class DerivedE<T> : Base<DerivedE<T>> where T : DerivedE<T> 
{ 
} 

public class DerivedF : DerivedE<DerivedF> 
{ 
} 

public class DerivedG : DerivedE<DerivedG> 
{ 
} 

new DerivedF().Changed(new DerivedG()); // does not compile 
new DerivedF().Changed(new DerivedF()); // does compile 

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx를 참조하십시오. 나는 그 기사에서 영감을 얻었다. 그는 단점과 찬성에 대해 이야기합니다. minitech로 의견

+0

컴파일되지 않은 또 다른 답변 : 형식이 일반 형식이 아니며 형식 인수로 사용할 수 없다는 오류가 발생합니다. –

+0

기본 예제가 컴파일됩니다. 코드에 대해 좀 더 공유해 주시면 기꺼이 살펴 보겠습니다. OP – skarmats

+0

에 대한 내 의견보기 파생 클래스가 상속되지 않는다고 말하지 않았습니다. 그 중 일부는 상속되지 않습니다. 어쨌든, 오류는 "비 제네릭 타입 은 타입 인자와 함께 사용할 수 없습니다"라고 클래스 라인에 표시됩니다. –

0

같은 대답에 따라 조정 청소 업, 그래서 그는 신용을 얻을해야하지만,이 예제에서는이 완전라는 이름의 클래스에 캐스팅하여 속성을 볼 수 있습니다 SubclassA의 변경 :

편집 할 수 있습니다.

namespace ConsoleApplication1 
{ 

    abstract class Base 
    {  
     protected abstract bool Changed<T>(T obj) where T : Base;  
     public bool Changed()  
     {   
      return Changed(this);  
     } 

     public String PropBase { get; set; } 
    } 

    class SubclassA : Base 
    { 
     public String PropA { get; set; } 

     protected override bool Changed<SubclassA>(SubclassA obj)  
     { 
      ConsoleApplication1.SubclassA myInstance = obj as ConsoleApplication1.SubclassA; 
      // Now can see PropA 
      myInstance.PropA = "A"; 
      return true; 
     } 


    } 

    class SubclassB : Base 
    { 
     protected override bool Changed<SubclassB>(SubclassB obj) 
     { 
      // can't see prop B here 
      // obj.PropB = "B"; 
      return true; 
     } 

     public String PropB { get; set; } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 

      SubclassB x = new SubclassB(); 

      x.Changed(); 

      Base y = new SubclassA(); 

      y.Changed(); 
     } 
    } 
} 
+0

나는 정말로 여기에 의아해하고있다 - 그것은 캐스트와 함께 아직도 그것을 보지 않는다! –

+0

어떤 버전의 .Net에서 태그를 추가하고 있습니까? 이것은 나를 위해 작동합니다. 닷넷 4.0 – user957902

+0

테스트 케이스는 .Net 3.5 및 .Net 4.0 모두에서 작동합니다. .NET 4.0 및 VS2010 용 SP1이 설치되어 있습니다. – user957902

관련 문제