有没有好的解决方法可以避免 FxCop 警告 CA1006?(注:此为提问标题,不需要回答)

25
我遇到了FxCop警告CA1006,Microsoft.Design "DoNotNestGenericTypesInMemberSignatures"的问题。具体来说,我正在设计一个从ReadOnlyCollection<Report<T>>继承的ReportCollection<T>类,其public构造函数需要以IList<Report<T>>为参数。
修复此警告的建议并不是很有用:
“要修复此规则的违规情况,请更改设计以删除嵌套类型参数。”目前我可以看到两种改变设计的方法:
1.将构造函数设置为internal。在我的情况下,这种方法行不通。构造函数必须为public,因为该集合类需要由程序集外部的代码实例化。
2.将构造函数取代为Report<T>[]而不是IList<Report<T>>。这是次优的,因为外部代码应该具有使用动态大小数据结构(如List<T>)而不是固定大小数组的灵活性。
目前,我已经放弃并抑制了这个警告。有更好的解决方案吗?
3个回答

31

我会把 FxCop 给出的警告当作是来自一个极端挑剔的同事提出的建议。忽略(禁止)其中一些建议是完全可以接受的。


2
这也是一个设计警告,因此有时这些可以被视为美学,特别是如果您不是设计公共API。+1 - Tim Lloyd

21

我同意,另一个可以忽略这个规则的好时机是当你需要说:

Func<IEnumerable<T>>
当然,你可以使用非泛型的IEnumerable,但是只要实现了IEnumerable(非泛型)接口的任何类型都可以使用。泛型(部分原因)的目的是限制可用于给定一组类型的类型。
我认为这个规则非常愚蠢。只有在有多个嵌套的泛型类型时才需要它。一个嵌套层级就足够安全了。
顺便说一句,我认为LINQ函数也会嵌套泛型类型,所以如果微软这样做,我们也可以这样做 :)

3
我不会设置任何“安全”嵌套级别的限制。泛型类型应该根据语义要求进行尽可能深的嵌套。接口对协变和逆变的支持限制意味着,期望一个 IDictionary<string,IList<string>> 的代码将无法接受一个 IDictionary<string,List<string>>,但是当嵌套泛型在语义上正确时,我更倾向于使用它们而不是试图规避它们。 - supercat

5

我同意在以下情况下可以忽略CA1006警告:

Func<IEnumerable<T>>

此外,您可以通过使用委托来简化代码,避免 CA1006 错误的出现:
public delegate IEnumerable<T> ChildrenDel<T>( T parent);

// was: GetDescendants<T>( this T item, Func< T, IEnumerable< T > > children )

public static IEnumerable< T > GetDescendants<T>( this T item, ChildrenDel<T> children )
{
    var stack = new Stack< T >();
    do {
        children( item ).ForEach( stack.Push );

        if( stack.Count == 0 )
            break;

        item = stack.Pop();

        yield return item;
    } while( true );
}

使用委托而不是Func<>的问题在于,Visual Studio不会在与父函数签名相同的弹出窗口中提示自定义委托的定义 - 而Func则很容易推断出lambda表达式。尽管如此,这是一个IDE问题而不是语言问题。 - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接