2014-07-24 23 views
1

我认识到这可能不需要重构。我只是开始尝试重构,并且我尝试使用这一行代码尝试这样做失败。我试图在VS2013中使用提取方法。唉。我在另外11个实例中使用了这一行的右侧。我将如何重构C#中的这一行代码?

Balance = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 

BalancedoubleMonthsToRunint

每请求:

for (int i = 0, chunksCnt = Chunks.Count; i < chunksCnt; i++) 
    { 
    if (Chunks[i].BeginDate < BeginDate) BeginDate = Chunks[i].BeginDate; 
    MonthsToRun = Math.Max(MonthsToRun, Utils.MonthDifference(BeginDate, Chunks[i].BeginDate) + Chunks[i].Balance.Count); 
    } 

    Balance = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 
    Default = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 
    Loss = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 
    Prepay = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 
    Principal = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 
    Interest = Enumerable.Repeat(0.0, MonthsToRun).ToList(); 

    for (int i = 0, chunksCnt = Chunks.Count; i < chunksCnt; i++) 
     { 
     offset = Utils.MonthDifference(BeginDate, Chunks[i].BeginDate); 

     for (int j = offset, balanceCnt = Chunks[i].Balance.Count; j < (balanceCnt + offset); j++) 
      { 
      Balance[j] += Chunks[i].Balance[j - offset]; 
      Default[j] += Chunks[i].Default[j - offset]; 
      Loss[j] += Chunks[i].Loss[j - offset]; 
      Prepay[j] += Chunks[i].Prepay[j - offset]; 
      Principal[j] += Chunks[i].Principal[j - offset]; 
      Interest[j] += Chunks[i].Interest[j - offset]; 
      } 

      if (Settings.runBacktesting) 
       { 
       foreach (KeyValuePair<Tuple<int, int, DateTime>, double> item in Chunks[i].TransProbChunk) 
       { 
       Utils.upsertDict(TransProbAgg, item.Key, item.Value); 
       //Create From Status - Month Totals Dictionary to create transition rates 
       Tuple<int, DateTime> key = new Tuple<int, DateTime>(item.Key.Item1, item.Key.Item3); 
       Utils.upsertDict(fromMonthTotals, key, item.Value); 
       } 
      } 
     } 
+2

为什么你认为这需要重构? _“平衡是双重的”_否,那么这将不会编译。也许一个'清单'。 –

+1

您通常不会在行级重构,而是概念化(类,接口等)级别。但是,如果您看到一个在整个代码中使用很多的模式,请尝试描述它。 – Groo

+0

这更让我的脚湿润。它可能不会。我只是好奇,假设它确实需要重构,那么这将是一个合适的方式。 – StephenWinburn

回答

1

我个人不觉得有必要重构该行。 重构通常是因为可读性/理解性或性能。 该行似乎是可读的。

如果因为重复而试图重构,那么你会重构以下内容,因为'= 0;'重复?

int x1 = 0; 
int x2 = 0; 
int x3 = 0; 
int x4 = 0; 
int x5 = 0; 
int x6 = 0; 
int x7 = 0; 

在这个愚蠢的情况下,你可以把它放在一行,但在真实的代码中,它将变得不可读。

你可以做的是使一个方法是“零”中的变量:

private void Zero<T>(int size, ref List<T> l1, ref List<T> l2, ref List<T> l3) 
    { 
     T[] zeroes = Enumerable.Repeat(default(T), size).ToArray(); 
     l1 = new List<T>(zeroes); 
     l2 = new List<T>(zeroes); 
     l3 = new List<T>(zeroes); 
    } 

,并调用它像:

Zero(MonthsToRun, ref Balance, ref Default, ref Loss, ...); 

如果你正在尝试做的,因为性能,然后一些类型的缓存可以帮助你......

public static class Sizer<T> 
{ 
    static Dictionary<int, T[]> _cache = new Dictionary<int, T[]>(); 

    public static void Init(ref List<T> list, int size) 
    { 
     T[] ret; 

     if (!_cache.TryGetValue(size, out ret)) 
     { 
      ret = Enumerable.Repeat(default(T), size).ToArray(); 
      _cache[size] = ret; 
     } 

     list = ret.ToList(); 
    } 
} 

Altough我不认为你能达到多少与它...

下面与上述类告诉(我也没在意优化)的增速大约是6倍:

 Random r; 
     const int repeatCount = 1000000; 
     List<int> list = null; 

     r = new Random(0); 
     var start = DateTime.Now.Ticks; 
     for (int i = 0; i < repeatCount; i++) 
     { 
      list = Enumerable.Repeat(0, r.Next(5,150)).ToList(); 
     } 
     var end = DateTime.Now.Ticks; 
     var t1 = end - start; 

     r = new Random(0); 
     start = DateTime.Now.Ticks; 
     for (int i = 0; i < repeatCount; i++) 
     { 
      Sizer<int>.Init(ref list, r.Next(5, 150)); // fill the list with default values for the type 
     } 
     end = DateTime.Now.Ticks; 
     var t2 = end - start; 
     var speedup = (double)t1/t2; 
+0

谢谢你的彻底。 – StephenWinburn

0

正如其他人提到你操作的结果是双打的名单。 如果你有十一行你使用Enumerable.Repeat并且至少有一个参数每行不一样,那么编写一个函数(也许是一个内联函数)是有意义的,但是我会这样做,因为它足够简单并且易于理解。

如果您需要让我们在11个地方列出n零,然后创建一个数组并在需要的地方使用它。

var zeroes = Enumberable.Repeat(0.0 ,MonthsToRun).ToArray(); 
//or even: 
//var zeroes = new double[MonthsToRun]; 
... 
var myList1 = new List<double>(zeroes); 
... 
var myList2 = new List<double>(zeroes); 

内联函数中使用的快捷键:

Func<double, int, List<double>> rv = (val, count) => { return Enumerable.Repeat(val, count).ToList(); }; 
... 
var myList1 = rv(0.0, MonthsToRun); 
... 

此外,如果你用钱的工作,然后用decimal工作:

decimal vs double! - Which one should I use and when?

+0

谢谢你的想法。 – StephenWinburn