C#:使 class 在 foreach 中可用
C#: making a class usable in foreach
我在这方面遇到了一些问题:
我必须在 C# 中创建一个 PrimeCollection class 来实现 IEnumerable 接口并动态生成素数集合。
所以如果我写这样的测试:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc)
Console.WriteLine(p);
}
它应该生成素数,直到达到 int32 限制。
到目前为止我有这个:
class PrimeCollection {
public IEnumerable<int> Primes() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
但是要进行生成,我需要这样调用它:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc.Primes())
Console.WriteLine(p);
}
我假设我需要使 class IEnumerable,而不是方法,但是我不知道如何即时生成数字。
根本没有理由拥有可实例化的 class。你没有持有状态。
public static class Prime
{
public static IEnumerable<int> Values()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
那么你可以这样使用它:
static void Main(string[] args)
{
foreach (int p in Prime.Values())
Console.WriteLine(p);
}
如果您想专门创建您的自定义 primes-enumerable,您可以将其定义为现有 linq 查询的包装器。像这样:
public class PrimesEnumerable : IEnumerable<int> {
public PrimesEnumerable() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
_internalEnumerable = ints.Where(x => !ints.TakeWhile(y => y*y<=x).Any(y => x % y == 0));
}
public readonly IEnumerable<int> _internalEnumerable;
public IEnumerator<int> GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
}
现在你可以 foreach 了:
var primes = new PrimesEnumerable();
int i = 0;
foreach (var prime in primes) {
if (i == 10)
break;
Console.WriteLine(prime);
i++;
}
Console.ReadLine();
注意:一定要修复@CarstenKönig 所说的错误。
你的意思是这样的?
class Program
{
static void Main(string[] args)
{
foreach(var prime in new PrimeCollection())
{
Console.WriteLine(prime);
}
Console.Read();
}
}
class PrimeCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0)).GetEnumerator();
}
}
我在这方面遇到了一些问题: 我必须在 C# 中创建一个 PrimeCollection class 来实现 IEnumerable 接口并动态生成素数集合。
所以如果我写这样的测试:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc)
Console.WriteLine(p);
}
它应该生成素数,直到达到 int32 限制。
到目前为止我有这个:
class PrimeCollection {
public IEnumerable<int> Primes() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
但是要进行生成,我需要这样调用它:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc.Primes())
Console.WriteLine(p);
}
我假设我需要使 class IEnumerable,而不是方法,但是我不知道如何即时生成数字。
根本没有理由拥有可实例化的 class。你没有持有状态。
public static class Prime
{
public static IEnumerable<int> Values()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
那么你可以这样使用它:
static void Main(string[] args)
{
foreach (int p in Prime.Values())
Console.WriteLine(p);
}
如果您想专门创建您的自定义 primes-enumerable,您可以将其定义为现有 linq 查询的包装器。像这样:
public class PrimesEnumerable : IEnumerable<int> {
public PrimesEnumerable() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
_internalEnumerable = ints.Where(x => !ints.TakeWhile(y => y*y<=x).Any(y => x % y == 0));
}
public readonly IEnumerable<int> _internalEnumerable;
public IEnumerator<int> GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
}
现在你可以 foreach 了:
var primes = new PrimesEnumerable();
int i = 0;
foreach (var prime in primes) {
if (i == 10)
break;
Console.WriteLine(prime);
i++;
}
Console.ReadLine();
注意:一定要修复@CarstenKönig 所说的错误。
你的意思是这样的?
class Program
{
static void Main(string[] args)
{
foreach(var prime in new PrimeCollection())
{
Console.WriteLine(prime);
}
Console.Read();
}
}
class PrimeCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0)).GetEnumerator();
}
}