C#泛型的反约束问题

3
Phil Haack's attempt on null or empty coalescing的启发,我试图为string对象编写一些扩展方法,以及IEnumerable<T>接口,以简化空值或空检查。然而,我遇到了问题:当我尝试调用AsNullIsEmptystring版本时,编译器会将我的字符串视为IEnumerable<char>,并且当然会给出错误的返回类型。
是否有任何方法可以在IEnumerable版本的定义上放置“反约束”,以便我可以告诉编译器在T的类型不是 string时使用该版本?类似于:
public static IEnumerable<T> AsNullIfEmpty(this IEnumerable<T> items)
    where T !: string

我知道我可以改变它们其中一个的名称,但为了保持一致性,我想使用相同的名称。
更新:事实证明,我的扩展方法问题通过修复一个简单而愚蠢的错误解决了(我使用了str.IsNullOrEmpty(),这是IEnumerable<T>上的扩展方法,而不是string.IsNullOrEmpty(str)...),但由于关于泛型反约束的问题仍然很有趣,所以我不会删除它。

编译器将采用最具体的可用方法。如果您实现了一个字符串并确保它在调用站点可用,那么您就不会遇到像描述的那样的问题。 - Rune FS
1个回答

8
唯一的方法是创建一个重载此扩展的方法,它接受一个字符串作为其“this”参数。
public static string AsNullIfEmpty(this string value)

这样做会导致特定类型版本被认为是比通用版本更好的重载匹配。

至于您具体的问题(“我能在泛型类型参数上指定'反约束条件'吗?”),答案是否定的。不过,您可以通过使用Obsolete属性来实现非常接近的效果。

[Obsolete("AsNullIfEmpty is not supported for strings.", true)]
public static string AsNullIfEmpty(this string value)

这将导致编译器报告这个重载的错误。

这就是我所拥有的 - 正如您在我的更新中看到的那样,扩展方法问题已经解决。(该问题存在于另一个错误之中...)。然而,是否有任何指定反约束条件的方法? - Tomas Aschan
当T为字符串时,您将获得具有相同签名的2种方法的良好智能感知。 - Yuriy Faktorovich
@Tomas:对于这个问题有一个简单的答案:不,没有办法指定反约束。 - LukeH
@Tomas:看一下我的编辑。严格的回答是“不行”,但最终结果可能的。 - Adam Robinson

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