Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以在foreach循环中增加标识符而不计算其表达式?_C# - Fatal编程技术网

C# 是否可以在foreach循环中增加标识符而不计算其表达式?

C# 是否可以在foreach循环中增加标识符而不计算其表达式?,c#,C#,我有一个对象的集合,我想通过迭代来最终识别某种类型的模式。目前,我有一组if语句来检查表达式的标志。例如,我有一些类似于if(!foundFirstObjectOfTypeA)的东西。一旦我找到类型A的第一个对象,我会将标志设置为true,我们将不再执行该块并继续执行下一个块。我有几种类型的模式需要识别,正因为如此,它创建了一大块难以理解且丑陋的if语句 是否有一种方法可以在不计算foreach循环中的表达式的情况下查看/查看标识符?如果我可以按照If(identifer==ObjectA&&i

我有一个对象的集合,我想通过迭代来最终识别某种类型的模式。目前,我有一组if语句来检查表达式的标志。例如,我有一些类似于if(!foundFirstObjectOfTypeA)的东西。一旦我找到类型A的第一个对象,我会将标志设置为true,我们将不再执行该块并继续执行下一个块。我有几种类型的模式需要识别,正因为如此,它创建了一大块难以理解且丑陋的if语句

是否有一种方法可以在不计算foreach循环中的表达式的情况下查看/查看标识符?如果我可以按照If(identifer==ObjectA&&identifer.next==ObjectB)的思路做一些事情,那么我的代码将更可读、更容易理解,而且我可以处理而不必设置标志


如果没有直接的方法/途径,有人有没有聪明的变通方法来模拟我想要的效果?

使用
for
循环来增加
I
,然后只看
对象[I]
对象[I+1]
。您使用的是哪种类型的集合?名单?阵列?一个
foreach
循环所做的就是对您隐藏计数器。如果我了解你的情况,绝对没有理由使用
foreach
循环而不是
for
循环

这适用于任何列表和任何对象序列:

功能:

public static bool ContainsSequence
    (System.Collections.Generic.IList<object> list, params object[] seq)
{
    for (int i = 0; i < list.Count() - seq.Count() + 1; i++)
    {
        int j;
        for (j = 0; j < seq.Count(); j++)
        {
            if (list[i + j] != seq[j])
                break;
        }
        if (j == seq.Count())
            return true;
    }
    return false;
}
private static void Main(string[] args)
{
    var A = new object();
    var B = new object();
    var C = new object();
    var D = new object();

    var list = new[] {A, B, C, D};
    Console.WriteLine(ContainsSequence(list, B, C, D));
    Console.WriteLine(ContainsSequence(list, A, D, C, B, A, C));
    Console.WriteLine(ContainsSequence(list, A, B));
}
True
False
True
输出:

public static bool ContainsSequence
    (System.Collections.Generic.IList<object> list, params object[] seq)
{
    for (int i = 0; i < list.Count() - seq.Count() + 1; i++)
    {
        int j;
        for (j = 0; j < seq.Count(); j++)
        {
            if (list[i + j] != seq[j])
                break;
        }
        if (j == seq.Count())
            return true;
    }
    return false;
}
private static void Main(string[] args)
{
    var A = new object();
    var B = new object();
    var C = new object();
    var D = new object();

    var list = new[] {A, B, C, D};
    Console.WriteLine(ContainsSequence(list, B, C, D));
    Console.WriteLine(ContainsSequence(list, A, D, C, B, A, C));
    Console.WriteLine(ContainsSequence(list, A, B));
}
True
False
True
如果您知道要查找多少个对象,则该函数可以变得更简单(如果您只查找两个对象,则这几乎是用户的答案-您只需添加AndrewS的边界检查,如下所示)


如果需要序列开头的索引,可以将my函数的返回类型更改为int,并返回
i
而不是
true
(返回
-1
而不是
false

如果使用for循环,可以这样做

for (int i = 0; i < list.Count - 1; i++)
    if (list[i] == ObjectA && list[i + 1] == ObjectB)
        ; // Your code
for(int i=0;i
我认为没有直接的支持,但您可以随时模仿

例如(解决方案的一部分):

静态IEnumerable topeakable(此IEnumerable流)
{
T prev=
foreach(流中的T项)
{
收益率返回新的可查看(上一个,项目);
prev=项目;
}
收益率返回新的可查看(项目,默认值(T));
}
更新:缺少零件

class Peekable<T>
{
    public Peekable(T current, T next)
    {
        Current = current;
        Next = next;
    }

    public T Current { get; private set; }
    public T Next { get; private set; }
}

static class PeekableAdaptor
{
    public static IEnumerable<Peekable<T>> ToPeekable<T>(this IEnumerable<T> stream)
    {
        var source = stream.GetEnumerator();

        if (!source.MoveNext()) 
            yield break;

        T prev = source.Current;

        while (source.MoveNext())
        {
            yield return new Peekable<T>(prev, source.Current);
            prev = source.Current;
        }

        yield return new Peekable<T>(prev, default(T));
    }
}

class Program
{
    static void Main(string[] args)
    {
        foreach (var pair in Enumerable.Range(1, 10).ToPeekable())
        {
            Console.WriteLine(pair.Current, pair.Next);
        }
    }
}
类可查看
{
可公开查看(T当前,T下一个)
{
电流=电流;
下一个=下一个;
}
公共T当前{get;私有集;}
公共T下一个{get;私有集;}
}
静态类可伸缩适配器
{
公共静态IEnumerable topeakable(此IEnumerable流)
{
var source=stream.GetEnumerator();
如果(!source.MoveNext())
屈服断裂;
T prev=电源电流;
while(source.MoveNext())
{
收益率返回新的可窥视值(上一个、源、当前);
prev=源电流;
}
收益率-收益率-新可窥视(上一个,默认值(T));
}
}
班级计划
{
静态void Main(字符串[]参数)
{
foreach(Enumerable.Range(1,10).ToPeekable()中的变量对)
{
Console.WriteLine(pair.Current,pair.Next);
}
}
}

IEnumerable
是一种非常轻的
仅向前推进的
迭代器实现。如果你看一下,只有三个成员:

作为解决方案,您可以手动迭代
IEnumerable
,也可以使用循环

bool MoveNext()
void Reset()
object Current
因此,唯一的操作是继续、重置和检索当前项。没有内置的能力来窥探接下来会发生什么

IEnumerable版本
bool someFlag=false;
IEnumerable collection=新对象[]{“string”,true,4,DateTime.Now};
使用(var enumerator=collection.GetEnumerator()){
while(true){
bool end=enumerator.MoveNext();
如果(!结束){
if(枚举数.Current.GetType()==typeof(字符串)){
end=enumerator.MoveNext();
if(!end&&enumerator.Current.GetType()==typeof(bool))
someFlag=true;
}
} 
如果(结束)中断;
}
}
循环版本
bool someFlag=false;
列表集合=新对象[]{“string”,true,4,DateTime.Now};
int i=0;
while(true){
bool end=i
根据我的答案,我提出了一个可能的解决方案。这将适用于任何类型的收集;即使是那些无法索引的

foreach (var item in ForEachHelper.Wrap(collection))
{
    Console.WriteLine("Position=" + item.Index.ToString());
    Console.WriteLine("Current=" + item.Current.ToString());
    if (item.HasNext)
    {
        Console.WriteLine("Next=" + item.Next.ToString());
    }
}
这是相关的代码

public static class ForEachHelper
{
    public sealed class Item<T>
    {
        public int Index { get; set; }
        public T Current { get; set; }
        public T Next { get; set; }
        public bool HasNext { get; set; }
    }

    public static IEnumerable<Item<T>> Wrap<T>(IEnumerable<T> enumerable)
    {
        IEnumerator<T> enumerator = enumerable.GetEnumerator();
        try
        {
            var item = new Item<T>();
            item.Index = 0;
            item.Current = default(T);
            item.Next = default(T);
            item.HasNext = false;
            if (enumerator.MoveNext())
            {
                item.Current = enumerator.Current;
                if (enumerator.MoveNext())
                {
                    item.Next = enumerator.Current;
                    item.HasNext = true;
                }
                while (item.HasNext)
                {
                    var next = new Item<T>();
                    next.Index = item.Index + 1;
                    next.Current = item.Next;
                    next.Next = default(T);
                    if (enumerator.MoveNext())
                    {
                        next.Next = enumerator.Current;
                        next.HasNext = true;
                    }
                    var current = item;
                    item = next;
                    yield return current;
                }
                yield return item;
            }
        }
        finally
        {
            enumerator.Dispose();
        }
    }
}
公共静态类ForEachHelper
{
公共密封类物品
{
公共int索引{get;set;}
公共T当前{get;set;}
公共T下一个{get;set;}
公共bool HasNext{get;set;}
}
公共静态IEnumerable包装(IEnumerable enumerable)
{
IEnumerator枚举器=可枚举的.GetEnumerator();
尝试
{
var item=新项();
项目指数=0;
项目当前=默认值(T);
item.Next=默认值(T);
item.HasNext=false;
if(枚举数.MoveNext())
{
item.Current=枚举数.Current;
if(枚举数.MoveNext())
{
item.Next=枚举数.Current;
item.HasNext=true;
}
while(item.HasNext)
{
var next=新项();
下一个,Inde