C# C Linq中带赋值的While循环

C# C Linq中带赋值的While循环,c#,linq,loops,syntax,random,C#,Linq,Loops,Syntax,Random,我想给变量vStreamID分配一个随机数。只要my dictionary md_StreamDict包含生成的号码,就应该新生成该号码 长版本: vStreamID = (new Random()).Next(1000, 9999).ToString(); while (md_StreamDict.ContainsKey(vStreamID)) { vStreamID = (new Random()).Next(1000, 9999).ToString(); } 我想看看LINQ风格

我想给变量vStreamID分配一个随机数。只要my dictionary md_StreamDict包含生成的号码,就应该新生成该号码

长版本:

vStreamID = (new Random()).Next(1000, 9999).ToString();
while (md_StreamDict.ContainsKey(vStreamID)) {
    vStreamID = (new Random()).Next(1000, 9999).ToString();
}
我想看看LINQ风格的东西

md_StreamDict.ContainsKey(vStreamID)
    .while( x => x = (new Random())
    .Next(1000, 9999)
    .ToString();

我知道上面的例子是香蕉。但如果有一个真正的方法来实现这一点,我会很高兴。不,我们不会再开始关于可读性的讨论了

现在我已经读了你的问题三遍了,我仍然不知道为什么或者怎么会有人用LINQ表达式来做这件事。我看到的唯一简短的解决方案是我在评论中写的:

var r = new Random();

do {
    vStreamID = r.Next(1000, 9999).ToString();
} while (md_StreamDict.ContainsKey(vStreamID));

您需要一种方法来生成流式随机数的无限枚举。您可以使用Enumerable.Range0、int.MaxValue进行近似计算:


那么r将包含字典中未包含的新键值。

如果我理解正确,您只需要一个已知范围内的数字,而这个数字不应该已经存在于字典中,因此请不要随机:


这里还有一些香蕉:

您可以创建生成随机数的IEnumerable,如:

public class RandomList : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        Random r = new Random();

        while (true)
            yield return r.Next(1000, 9999);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

一种方法是使用收益率返回值

 private static Random rand = new Random();

    private static void Test()
    {
        Dictionary<string, string> values = new Dictionary<string, string>();
        string vStreamId = GetNewValues().Where(x => !values.ContainsKey(x)).First();
    }

    public static IEnumerable<string> GetNewValues()
    {
        While(true)
        {
           yield return rand.Next(1000, 9999).ToString();
        }
    }

请注意,如果在每个循环上生成一个新的随机数,则每次都会得到基于系统时钟的相同值。

如果使用do{}while;,即使是长版本也可能更短:-所以你只需要一个明确的数字,这个数字不应该已经在字典里了,为什么你需要随机的呢?我认为神经缺陷需要在他的字典里有一个新的条目,其中键是随机的,字典里不存在。为什么是linq,dunno.永远不要给新Random打那么多次电话。只需创建一个Random实例,然后重用该随机数生成器。否则,您可能会创建相同的随机实例—时间可能不会从一个实例更改到下一个实例,然后。下一个。。。将为每个随机实例提供相同的数字。如果希望9999成为可能的结果,请改用.Next1000、10000。这将生成一个值。我不确定您是否理解Jon,GetNewValues函数在每次调用时都返回一个新值,LINQ语句将选择字典中不存在的第一个值。请尝试运行它。获取新值将生成一个随机数,然后返回。你必须做真正的收益回报…这不会创建一个无限的列表,你不能100%确定它将包含1000-9999之间的所有值。你要么在真正产生random.Next的时候做,要么在该范围内创建int列表并洗牌。@JonB:没错。虽然我认为如果你一路走到4294967296却没有找到丢失的钥匙,你可以写一本关于统计异常的书。如果你的字典已经满了,你需要等待很长时间才能用任何方法找到一个漏洞。不要在循环中创建一个随机的实例!见@OlivierJacot Descombes:好的观点。更新。我只是盲目地用LINQ格式复制OP的原始逻辑。@Neurodefekt这总是给出dict中没有的最低四位数或小于10999的数字。你甚至可以说。FirstOrDefaultn=>!迪克特·康纳斯基。在任何情况下,如果dict包含1000和10998之间的所有键,则返回0。哎呀,你知道Range10009999给出的数字是1000到10998吗?@sll:让我更明确一点:new Random.next10009999对应的范围是Enumerable.Range10008999,所以你的答案错了。如果原来的海报真的是指新的Random.next100010000,那就是Enumerable.range10009000。
public class RandomList : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        Random r = new Random();

        while (true)
            yield return r.Next(1000, 9999);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
// I guess one could implement a seed constructor, if one was so inclined
RandomList rl = new RandomList(); 

int vStreamID = rl.SkipWhile(i => md_StreamDict.ContainsKey(i)).First();
 private static Random rand = new Random();

    private static void Test()
    {
        Dictionary<string, string> values = new Dictionary<string, string>();
        string vStreamId = GetNewValues().Where(x => !values.ContainsKey(x)).First();
    }

    public static IEnumerable<string> GetNewValues()
    {
        While(true)
        {
           yield return rand.Next(1000, 9999).ToString();
        }
    }