什么时候在这种情况下实例化对象?

时间:2014-05-02 11:56:30

标签: c# design-patterns

我多次对此表单的烦恼感到磕磕绊绊,所以我的问题是:代码方案的最佳模式/实践如下所示?

这是我最近写的方法体的一个例子:

public HashSet<char> SomeCharacters(IEnumerable<string> _hashes){

    HashSet<char> Result = new HashSet<char>();
    bool _firstpass = true;

    foreach (string _hash in _hashes) {
        if (_firstpass) {
            Result = new HashSet<char>(_hash);
            _firstpass = false;
        }
        else {
            // ...
            // some code that uses Result
        }
    }
    return Result;
}

这很好用,但令我讨厌的是第一行

HashSet<char> Result = new HashSet<char>();

我本能地喜欢用HashSet<char> Result;替换。编译器不会让我,因为else块使用Result它不会识别为instanciated,虽然我知道它将在else块执行时。< / p>

上面的方法迫使我两次创建Result,这有很多原因(性能,代码美学,......)并不好。

请将此问题视为有关此类情况的问题,而不仅仅关注此特定示例。谢谢!

2 个答案:

答案 0 :(得分:5)

最初只需将null分配给变量:

HashSet<char> Result = null;

然后你也可以摆脱_firstpass变量:

HashSet<char> Result = null;
foreach (string _hash in _hashes) {
    if (Result == null) {
        Result = new HashSet<char>(_hash);
    }
    else {
        // ...
        // some code that uses Result
    }
}

如果迭代字符串集合的唯一目的是将字符串的所有字符放在HashSet<char>中,那么你可以这样做:

var Result = new HashSet<char>(_hashes.SelectMany(s => s));

这里的原则是,有时您可以使用“first pass create and add”逻辑将循环重写为更简单的LINQ语句,在这些语句中构建序列,然后使用ToList创建最终对象,或者在本例中为{ {1}}构造函数。

答案 1 :(得分:1)

你可以重构删除标志:

public HashSet<char> SomeCharacters(IEnumerable<string> _hashes){

    string first = _hashes.FirstOrDefault();
    if(first == null) return new HashSet<char>();

    HashSet<char> Result = new HashSet<char>(first);

    foreach (string _hash in _hashes.Skip(1)) {
        // ...
        // some code that uses Result
    }
    return Result;
}

您需要确保不止一次枚举_hashes是安全的。