我希望Enumerable.Empty<string>()
返回一个空字符串数组。相反,它似乎返回一个具有单个null
值的数组。这打破了DefaultIfEmpty
之类的其他LINQ运算符,因为可枚举实际上并不是空的。这似乎没有在任何地方记录,所以我想知道我是否遗漏了某些东西(概率为99%)。
GameObject Class
public GameObject(string id,IEnumerable<string> keywords) {
if (String.IsNullOrWhiteSpace(id)) {
throw new ArgumentException("invalid", "id");
}
if (keywords==null) {
throw new ArgumentException("invalid", "keywords");
}
if (keywords.DefaultIfEmpty() == null) { //This line doesn't work correctly.
throw new ArgumentException("invalid", "keywords");
}
if (keywords.Any(kw => String.IsNullOrWhiteSpace(kw))) {
throw new ArgumentException("invalid", "keywords");
}
_id = id;
_keywords = new HashSet<string>(keywords);
}
测试
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void EmptyKeywords() {
GameObject test = new GameObject("test",System.Linq.Enumerable.Empty<string>());
}
答案 0 :(得分:8)
看起来你期待这种情况:
keywords.DefaultIfEmpty() == null
评估为true
。但是,如果源序列为空,DefaultIfEmpty
将返回包含元素类型(在本例中为string
)的默认值的单例序列。因此,它将返回包含null
的序列。这本身不是null
,但条件会返回false
。
答案 1 :(得分:1)
您误解了public static WebClient webclient = new WebClient();
public static string GetIP()
{
string externalIP = "";
externalIP = webclient.DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
return externalIP;
}
的实施,这是它的实施from the reference source。
DefaultIfEmpty
所以它的作用是如果public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source) {
return DefaultIfEmpty(source, default(TSource));
}
public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue) {
if (source == null) throw Error.ArgumentNull("source");
return DefaultIfEmptyIterator<TSource>(source, defaultValue);
}
static IEnumerable<TSource> DefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue) {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) {
do {
yield return e.Current;
} while (e.MoveNext());
}
else {
yield return defaultValue;
}
}
}
不为空它只返回IEnumerable<T>
,如果IEnumerable<T>
为空则返回新的IEnumerable<T>
,其中包含一个对象它的值为IEnumerable<T>
。它将永远不会返回default(T)
,这是您的测试所测试的。如果你想测试这个,你需要做
null
然而,这将导致多次评估if(keywords.DefaultIfEmpty().First() == null)
。我会放弃LINQ,就像LINQ方法一样,并且做得很长(这也消除了IEnumerable<string>
内部的额外评估。)
new HashSet<string>(keywords)
这使得您只能在 public GameObject(string id,IEnumerable<string> keywords)
{
if (String.IsNullOrWhiteSpace(id)) {
throw new ArgumentException("invalid", "id");
}
if (keywords==null) {
throw new ArgumentException("invalid", "keywords");
}
_keywords = new HashSet<string>();
using (var enumerator = keywords.GetEnumerator())
{
if (e.MoveNext())
{
do
{
if(e.Current == null)
throw new ArgumentException("invalid", "keywords");
_keywords.Add(e.Current);
} while (e.MoveNext());
}
else
{
throw new ArgumentException("invalid", "keywords");
}
}
_id = id;
}
上循环一次。
答案 2 :(得分:0)
这会解决您的问题吗?
public GameObject(string id, IEnumerable<string> keywords) {
if (String.IsNullOrWhiteSpace(id)) {
throw new ArgumentException("invalid", "id");
}
if (keywords == null || !keywords.Any()
|| keywords.Any(k => String.IsNullOrWhiteSpace(k))) {
throw new ArgumentException("invalid", "keywords");
}
_id = id;
_keywords = new HashSet<string>(keywords);
}
*通过@ScottChamberlain&amp;的建议改进了代码@ginkner