如何促进C#变量的类型重构?

时间:2014-02-16 23:56:25

标签: c# generics types refactoring

例如,我有一个像这样的代码片段:

IEnumerable<int> _en;
object _lock = new Object();

void Enumerate()
{
    IEnumerable<int> en = null;

    lock (_lock)
    {
        en = _en;
        _en = new List<int>();
        // ...
    }

    foreach (var i in en)
    {
        // ...
    }
}

我想将商品类型从int更改为double,因此我至少有3个地方可以参加并更改它。为了方便这一点,以下内容是否有意义?还有什么我可以做的吗?

IEnumerable<int> _en;
object _lock = new Object();

void Enumerate()
{
    var en = GetDefault(_en);

    lock (_lock)
    {
        en = _en;
        _en = CreateEmptyList(_en);
        // ...
    }

    foreach (var i in en)
    {
        // ...
    }
}

static T GetDefault<T>(T arg)
{
    return default(T);
}

static List<T> CreateEmptyList<T>(IEnumerable<T> arg)
{
    return new List<T>();
}

1 个答案:

答案 0 :(得分:1)

问题:

当我决定理解它时,您希望通过创建某种方式来减少在重构期间更改代码所需的整体位置数量,从而最大限度地减少在您的工作环境中不断变化的需求中的重复重构任务的工作量。

一种可能的解决方案:

你可以混淆到某一点。

重要说明:如果要将double更改为int,则可能必须重构调用代码的位置。基本上协方差和逆变发挥作用。

double example = 2; // works
int example2 = 2.5; // needs to manually be refactored
  • 因此,考虑到这一点,您可以将您的类创建为接受value type的通用基类,然后创建一个定义value type的传递子类( int,double等。)

  • 您希望提供不需要显式创建的方法,比如说全部列表,因为在重构时,所有这些都必须更改。

以下是可以执行以下操作的方法示例:

// We use params T[] here to reduce the need for any calling code to declare,
// for example, a List<int>, which would later need to potentially be changed in
// many places.
public void SetEnumerable(params T[] value)
{
    _en = value;
}    
  • 您只需使用数值来调用它:(根据我的第一个注释,如果您将基础通用类型从int更改为double,这将继续有效;但是如果您从double更改为int,然后调用代码在重构之前不会编译。

示例:

// Here we use the SetEnumerable method without declaring a List<int>.
// Therefore, if you later change underlying type to double, the code 
// below can remain unchanged.
var myEnumerable = new MyEnumerable();
myEnumerable.SetEnumerable(1, 2, 3); 

类结构可能如下所示:

注意我并不是说这是一个很好的做法,而只是试图在这种情况下为你的不同问题提供一个可能的解决方案。 此解决方案在性能方面的优点和/或是否是一个好主意超出了本答案的范围:)

public class MyEnumerable : EnumerateBase<int> { }

public class EnumerateBase<T> where T :  struct 
{
    private IEnumerable<T> _en;
    object _lock = new Object();

    public void SetEnumerable(params T[] value)
    {
        _en = value;
    }

    public void Enumerate()
    {
        IEnumerable<T> en = null;

        lock (_lock)
        {
            en = _en;
            _en = new List<T>();
            // ...
        }

        foreach (var i in en) { /* ... */ }
    }
}

在此示例中,数据类型int仅在一个地方声明,使重构相对简单。

希望这能为您提供一些思考和洞察力,让您了解如何解决您所陈述的问题。