2013-08-13 3 views
1

나는 열심히이 접근 방식을 수정 찾으려고 노력 데 이러한 데이터 구조C#을 상속, 새 수정 및 제네릭

의 컬렉션을 포함

public abstract class Flow 
{ 
    public virtual double Value { get; set; } 
    public virtual DateTime Time { get; set; } 
} 

public class InboundFlow : Flow 
{ 
} 

public class OutboundFlow : Flow 
{ 
} 

내 비즈니스 오브젝트 :

내 데이터 구조를

public abstract class Fluent 
{ 
    public virtual IList<Flow> FlowCollection { get; set; } 
    public virtual double InitialBaseflow { get; set; } 
} 

public class Affluent : Fluent 
{ 
    public new virtual IList<InboundFlow> FlowCollection { get; set; } 
} 

public class Effluent : Fluent 
{ 
    public new virtual IList<OutboundFlow> FlowCollection { get; set; } 
} 

내가 노력하고있어 일반적인 방법은 사용 :

private static void FindInitialBaseflow<T>(ref T fluent) where T : Fluent 
    { 
     var linqFluent = fluent; 

     var flows = linqFluent.FlowCollection.ToList().FindAll(
        flow => 
        flow.Time >= SOME_DATE && 
        flow.Time < SOME_OTHER_DATE); 
     var initialBaseflow = flows.Average(flow => flow.Value); 
     fluent.InitialBaseflow = Math.Round(initialBaseflow, 5); 
    } 

내 문제는 linq 메서드에서 "linqfluent.FlowCollection"을 호출하면 Fluent의 FlowCollection null이 호출됨을 의미합니다.

어떻게 대신 자녀의 재산을 사용할 수 있습니까? 감사! 당신은 당신도 Flow의 하위 클래스를 필요로하지 않는다는 것을 일단

public class Fluent<T> 
    where T : Flow 
{ 
    public IList<T> FlowCollection { get; set; } 
    public double InitialBaseflow { get; set; } 
} 

, 당신은 할 수 있습니다

+0

는'new' 새로운 버전으로 속성을 덮어, 당신은 그것을 무시해야 할 것입니다. 하지만 당신은 공분산에 문제가 있습니다. – Femaref

+0

FindInitialBaseflow를 호출하는 방법을 보여줄 수 있습니까 ?? FindInitialBaseflow < Affluent > (ref affluentobject)가 기본 클래스 콜렉션에 대한 호출을 수행합니다. –

+0

@Ashley John : FindInitialBaseflow (ref 풍족한) 및 풍족한 서식의 풍족한 서식 –

답변

1

당신은 그것에서 상속 클래스 유형을 지정할 수 있도록 Fluent 일반적인 내 컬렉션을 만들 필요가 그냥 콘크리트로 만드십시오.

그것의 사용은 쉽게이 모델에 맞게 수정 될 것이다 :

private static void FindInitialBaseflow<T>(Fluent<T> fluent) 
    where T : Flow 
{ 
    var linqFluent = fluent; 

    var flows = linqFluent.FlowCollection.Where(
       flow => 
       flow.Time >= SOME_DATE && 
       flow.Time < SOME_OTHER_DATE); 
    var initialBaseflow = flows.Average(flow => flow.Value); 
    fluent.InitialBaseflow = Math.Round(initialBaseflow, 5); 
} 

또한이 방법에 fluent을 설정하지 않을 때문에, 참조로 전달할 필요가 없습니다 있습니다. 이미 클래스이므로, 자체 참조입니다. 참조 된 객체의 돌연변이가 호출자에 의해 관찰됩니다.

-1

제네릭은 잘못된 도구입니다. 유형에 따라 올바른 구현이 호출되도록 다형성을 사용해야합니다. 예를 들어

:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Text; 

namespace ConsoleApp 
{ 
    public abstract class Flow 
    { 
     public virtual double Value { get { return new Random().Next() ; } }//these values are just for demonstration purposes 
     public virtual DateTime Time 
     { 
      get 
      { 
       return DateTime.MinValue.AddYears(1); 
      } 
     } 
    } 

    public class InboundFlow : Flow 
    { 
    } 

    public class OutboundFlow : Flow 
    { 
    } 

    public abstract class Fluent 
    { 
     IList<Flow> _flowCollection; 
     public virtual IList<Flow> FlowCollection 
     { 
      get { return _flowCollection; } 
      set { _flowCollection = value; } 
     } 

     private double _initialBaseflow; 
     public virtual double InitialBaseflow 
     { 
      get { return _initialBaseflow; } 
      set { _initialBaseflow = value; } 
     } 

     public Fluent() 
     { 
      FlowCollection = new List<Flow>(); 
     } 
    } 

    public class Affluent : Fluent 
    { 
     //public new virtual IList<InboundFlow> FlowCollection { get; set; }//Keep the property polymorphic 

     public Affluent() 
     { 
      FlowCollection = new List<Flow>(); 
     } 
    } 

    public class Effluent : Fluent 
    { 
     //public new virtual IList<OutboundFlow> FlowCollection { get; set; } 

     public Effluent() 
     { 
      FlowCollection = new List<Flow>(); 
     } 
    } 

    class Program 
    { 
     public static DateTime SOME_DATE { get { return DateTime.MinValue; } } 
     public static DateTime SOME_OTHER_DATE { get { return DateTime.Now; } } 

     static void Main(string[] args) 
     { 
      var inbound = new InboundFlow(); 
      var inbound2 = new InboundFlow(); 
      var outbound = new OutboundFlow(); 
      var a = new Affluent();    
      a.FlowCollection.Add(inbound); 
      a.FlowCollection.Add(inbound2); 
      FindInitialBaseflow(a); 
     } 

     private static void FindInitialBaseflow(Fluent fluent) 
     { 
      var linqFluent = fluent; 

      var flows = linqFluent.FlowCollection.ToList().FindAll(
         flow => 
         flow.Time >= SOME_DATE && 
         flow.Time < SOME_OTHER_DATE); 
      var initialBaseflow = flows.Average(flow => flow.Value); 
      fluent.InitialBaseflow = Math.Round(initialBaseflow, 5); 
     } 
    } 
} 
+0

그러나 하위 유형의 특성은 'FlowCollection' 특성을 숨기며, 이를 무시하므로이 경우 다형성 (polymorphic) 동작을 얻지 못합니다. 이것은 OP가 그의 코드로 관찰 한 문제이며, 당신의 변경은 그 행동을 바꾸지 않는다. – Servy

+0

@Servy - OP가 그의 속성을 올바르게 설정하지 않았기 때문에 그가 다형성을 사용할 수 없거나 사용해서는 안된다는 것을 의미하지는 않습니다. 제네릭은 OP가 요구 한 다형성 행동에 좋지 않습니다. –

+1

답을 원하면 자신의 속성을 올바르게 설정하는 방법을 보여줄 필요가 있습니다. 그의 속성이 모두 같은 유형으로 해석되는 것은 아닙니다. 다형성 (polymorphic) 동작은 * 모든 콜렉션이 동일한 컴파일 타임 타입을 요구 *합니다. 그것이 불가능하기 때문에, 제네릭은 분명히 갈 길입니다. 다형성 솔루션 *이 OP의 코드와 똑같은 문제가 아닌 * 실제로 작동한다는 것을 보여줄 수 있다면 * 꼭 보길 원합니다. – Servy