2015-02-25 3 views
1

У меня есть следующий класс:Как можно обобщить функцию расширения диапазона?

public class State { 
    public DateTime Created { get; set; } 
    public Double A { get; set; } 
    public Double B { get; set; } 
} 

Тогда у меня есть два состояния:

State start = new State { Created = DateTime.UtcNow, A = 10.2, B = 20.5 } 

State end = new State { Created = DateTime.UtcNow.AddDays(40), A = 1, B = 80 } 

Я хотел бы создать список между началом и концом, где значения A и B эволюционировать в линейном между начальным и конечным значениями.

Я был в состоянии создать список выглядит следующим образом:

IList<DateTime> dates = new Range<DateTime>(start.Created, end.Created,).Expand(DateInterval.Day, 1) 

Range и расширить несколько помощников я создал ...

Что является лучшим способом для создания эволюции ценностей?

Моя идея будет делать что-то вроде:

IList<State> states = new Range<State>(// here "tell" how each property would evolve ...) 

UPDATE

Range Class

public class Range<T> where T : IComparable<T> { 

    private T _minimum; 
    private T _maximum; 

    public T Minimum { get { return _minimum; } set { value = _minimum; } } 
    public T Maximum { get { return _maximum; } set { value = _maximum; } } 

    public Range(T minimum, T maximum) { 
     _minimum = minimum; 
     _maximum = maximum; 
    } // Range 

    public Boolean Contains(T value) { 
     return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(Maximum) <= 0); 
    } // Contains 

    public Boolean ContainsRange(Range<T> Range) { 
     return this.IsValid() && Range.IsValid() && this.Contains(Range.Minimum) && this.Contains(Range.Maximum); 
    } // ContainsRange 

    public Boolean IsInsideRange(Range<T> Range) { 
     return this.IsValid() && Range.IsValid() && Range.Contains(this.Minimum) && Range.Contains(this.Maximum); 
    } // IsInsideRange 

    public Boolean IsValid() { 
     return Minimum.CompareTo(Maximum) <= 0; 
    } // IsValid 

    public override String ToString() { 
     return String.Format("[{0} - {1}]", Minimum, Maximum); 
    } // ToString 

} // Range 

Несколько Диапазон расширения:

public static IEnumerable<Int32> Expand(this Range<Int32> range, Int32 step = 1) { 
    Int32 current = range.Minimum; 
    while (current <= range.Maximum) { 
    yield return current; 
    current += step; 
    } 
} // Expand 

public static IEnumerable<DateTime> Expand(this Range<DateTime> range, TimeSpan span) { 
    DateTime current = range.Minimum; 
    while (current <= range.Maximum) { 
    yield return current; 
    current = current.Add(span); 
    } 
} // Expand 
+1

Я правильно понял: вы хотите заполнить список 'start',' end' и 'n' количеством интерполированных состояний? – cubrr

+0

Что вы пробовали? Похоже, что вычисление дельта на основе разницы, деленной на количество точек данных минус 1, сделало бы трюк. – juharr

+0

То, что я пытаюсь сделать, это создать вспомогательные классы, которые выполняются так же, как и для DateTime ... Поэтому вместо того, чтобы применять его к DateTime или Int32, я применил бы его к свойствам класса. –

ответ

1
var magicNumber = 40; 

var start = new State {Created = DateTime.UtcNow, A = 10.2, B = 20.5}; 
var end = new State {Created = DateTime.UtcNow.AddDays(magicNumber), A = 1, B = 80}; 

var stateList = new List<State>(magicNumber); 

for (var i = 0; i < magicNumber; ++i) 
{ 
    var newA = start.A + (end.A - start.A)/magicNumber * (i + 1); 
    var newB = start.B + (end.B - start.B)/magicNumber * (i + 1); 
    stateList.Add(new State { Created = DateTime.UtcNow.AddDays(i + 1), A = newA, B = newB }); 
} 
+0

Я уверен, что его следует разделить на n-1 вместо n. Это дельта будет (end-start)/(n-1). – juharr

+0

если конец равен 6, а начало - 2, а n - 3, вы хотите 2,4,6. Дельта равна (6-2)/(3-1) = 2. И вы определенно хотите разделить дельта на ноль, чтобы первый получил 2, поэтому он будет умножен на i, а не i + 1. – juharr

+0

Извините, может быть, я объяснил, что неправильно, по моей идее было бы делать то, что вы делаете, но создав класс ... Я обновил свой вопрос .. Как вы думаете, это возможно? –

0

Итак, вы перешли на этап генерации, где метод инъекции «мутация», который будет применять вашу интерполяцию, станет логичным. Поскольку вы не ограничиваете достаточно далеко, чтобы знать, как интерполировать шаги, вам может понадобиться фабричный метод для создания экземпляров Func<T,T>.

Например, если есть два свойства, значения которых сдвигаются в вашем T, вы сможете контролировать их скорость изменения таким образом.

public class Point 
{ 
    int X {get;set;} 
    int Y {get;set;} 
} 

public static IEnumerable<T> Expand(this Range<T> range, Func<T,T> stepFunction) 
           where T: IComparable<T> 
{ 
    var current = range.Minimum; 
    while (range.Contains(current)) 
    { 
     yield return current; 
     current = stepFunction(current); 
    } 
} 

// in method 
var pointRange = new Range<Point>(
        new Point{ X=0,Y=0}, new Point{ X=5, Y=20}); 

foreach (Point p in pointRange.Expand(p => new Point{ p.X + 1, p.Y + 4}) 
+0

Это, к сожалению, я не могу сделать Point для реализации IComparable, поскольку это Entity Framework Poco ... Так что я получаю ошибку: Тип «Точка» не может использоваться как параметр типа «T» в родовом типе или метод 'Диапазон '. Нет никакого неявного преобразования ссылок из «Точка» в «Точка». –

+0

Вы можете, конечно, реализовать IComparable на EF POCO .... –

Смежные вопросы