4

.NET(或某种标准扩展方法)中有没有办法询问枚举问题?

例如,当前项是枚举中的第一项还是最后一项:

string s = "";

foreach (var person in PeopleListEnumerator) {

  if (PeopleListEnumerator.IsFirstItem) s += "[";

  s += person.ToString();

  if (!PeopleListEnumerator.IsLastItem) s += ",";
  else s += "]";
}
4

10 回答 10

8

只是为了好玩,一个不需要急切评估并且具有单个局部变量(除了枚举数)的一般问题的解决方案:

static class TaggedEnumerableExtensions
{
    public class TaggedItem<T>
    {
        public TaggedItem(T value, bool isFirst, bool isLast)
        {
            IsFirst = isFirst;
            IsLast = isLast;
            Value = value;
        }
        public T Value { get; private set; }
        public bool IsFirst { get; private set; }
        public bool IsLast { get; private set; }
    }
    public static IEnumerable<TaggedItem<T>> ToTaggedEnumerable<T>(this IEnumerable<T> e)
    {
        using (var enumerator = e.GetEnumerator()) {
            if (!enumerator.MoveNext())
                yield break;
            var current = enumerator.Current;
            if (!enumerator.MoveNext()) {
                yield return new TaggedItem<T>(current, true, true);
                yield break;
            } else {
                yield return new TaggedItem<T>(current, true, false);
            }

            for (;;) {
                current = enumerator.Current;
                if (!enumerator.MoveNext()) {
                    yield return new TaggedItem<T>(current, false, true);
                    yield break;
                }
                yield return new TaggedItem<T>(current, false, false);
            }
        }
    }
}

测试:

class Program
{
    static void Main(string[] args)
    {
        foreach (var item in Enumerable.Range(0, 10).ToTaggedEnumerable()) {
            Console.WriteLine("{0} {1} {2}", item.IsFirst, item.IsLast, item.Value);
        }
    }
}
于 2009-06-28T23:47:26.070 回答
3

如果您的收藏是列表,您可以执行以下操作:

string s = "[" + String.Join(",", PeopleList.ToArray()) + "]";
于 2009-06-28T23:40:30.000 回答
2

从来没听说过。不过,您可以尝试自己编写此类扩展方法。或者跟踪其他地方的第一个/最后一个项目。

Eric Lippert 最近发表了一篇关于此类问题的博客文章,并提出了一些关于如何修改问题描述以更准确地反映您真正想要的内容的想法。

在这种情况下,您最好使用带有一些 LINQ的String.Join :

String.Join(
  ",",
  (from p in PeopleListEnumerator
  select p.ToString()).ToArray()
)
于 2009-06-28T23:36:19.620 回答
1

IEnumerable 接口不定义或期望它返回的项目以任何给定的顺序排列。所以“第一”的概念并不总是适用。

但是,对于这种特殊模式,这就是我所做的

StringBuilder result = new StringBuilder();
result.Append( '[' );

foreach( var person in PeopleListEnumerator )
{
    if( result.Length > 1 )
        result.Append( ',' );
    result.Append( person.ToString() );
}

result.Append( ']' );
于 2009-06-28T23:54:12.687 回答
1

使用 LINQ,您可以执行以下操作:

string s = 
    string.Format("[{0}]", string.Join(",",PeopleListEnumerator.Select(p => p.ToString()).ToArray()));
于 2009-06-28T23:58:21.667 回答
1

Jon Skeet 编写了Smart Enumerations来提供这种功能,它们是MiscUtils库的一部分。

也就是说,正如许多其他人指出的那样,您的具体示例最好通过 String.Join() 方法来解决。编写通用string Join(this IEnumerable<T>,string)扩展并不难,然后可以在更多情况下使用,而不必求助于烦人的临时数组。

于 2009-06-29T00:01:37.743 回答
0

我发现自己定义和使用“布尔优先”局部变量,例如:

string s = "[";
bool first = true;

foreach (var person in PeopleListEnumerator) {

  if (first)
    first = false;
  else
    s += ",";
  s += person.ToString();
}
s += "]";
于 2009-06-28T23:36:37.573 回答
0

此代码与您真正想要完成的代码非常匹配:

StringBuilder s = new StringBuilder("[");
string delimiter = "";

foreach (var person in PeopleListEnumerator) {  
  s.Append(delimiter).Append(person.ToString());
  delimiter = ",";
}

return s.Append("]").ToString();
于 2009-06-28T23:53:47.323 回答
0

我给这只猫剥皮的方法(是的,有很多方法)是:

StringBuilder sb = new StringBuilder();

foreach (var person in PeopleListEnumerator )
{
    sb.AppendFormat(",{0}", person.ToString());
}

string s = "[" + sb.ToString().Substring(1) + "]";

希望这可以帮助...

于 2009-06-29T00:29:23.817 回答
-2

在 .NET 中,枚举没有顺序的概念,除了按值。如果您想要第一个和最后一个枚举,我建议明确定义这些第一个和最后一个值是什么。下面的枚举就是一个例子:

public enum PlayerType : byte
{
    Starter = byte.MinValue,
    RegularPlayer = 1,
    BenchWarmer = 2,
    Closer = byte.MaxValue
}

然后,您可以表达类似于以下内容:

List<byte> values = new List<byte>((byte[])Enum.GetValues(typeof(PlayerType)));

PlayerType starter = (PlayerType)values.Min();
PlayerType closer = (PlayerType)values.Max();
于 2009-06-28T23:51:50.010 回答