我有一个工厂函数,并希望用它来创建一个Enumerable。在C#中,我没有找到一种直接的声明式方法来完成这项工作。所以我这样做了:
public IEnumerable<Contact> Get()
{
return Enumerable.Range(1, 5).Select(x => GenerateRandomContact());
}
还有更好的方法吗?
// Expected format
public IEnumerable<Contact> Get()
{
return Enumerable.Generate(GenerateRandomContact).Take(5);
}
答案 0 :(得分:6)
类似的东西:
public static IEnumerable<T> Generate(Func<T> generator)
{
while(true)
yield return generator.Invoke();
}
但是你不能扩展静态类。所以你应该将它放在一个帮助类中。
答案 1 :(得分:1)
public IEnumerable<Contact> Get()
{
for(int i = 1; i <= 5; i ++)
{
yield return GenerateRandomContact();
}
}
或者如果您想要特定金额,可以执行此操作
public IEnumerable<Contact> Get(int number)
{
for(var i = 1; i <= number; i ++) //is the same as for (var i = 1;; i++) you got the idea
{
yield return GenerateRandomContact();
}
}
你期待像Enumerable.Generate()
这样的东西为了获取要枚举的元素列表,Generate方法应该返回一个Enumerable Value。您正在尝试根据您的方法为Enumerable创建扩展方法。在此之前尝试查看Range
的实现public static IEnumerable<int> Range(int start, int count)
{
long max = ((long)start) + count - 1;
if (count < 0 || max > Int32.MaxValue) throw Error.ArgumentOutOfRange("count");
return RangeIterator(start, count);
}
static IEnumerable<int> RangeIterator(int start, int count)
{
for (int i = 0; i < count; i++) yield return start + i;
}
在yield的情况下,.NET会根据特定的数量为您创建IEnumerable类。也许你应该考虑在Generate方法上传递数量,或者像Concat那样的其他扩展,你应该传递IEnumerable,请看下面它们如何传递给Contact mehotd IEnumerable第一个变量
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ConcatIterator<TSource>(first, second);
}
说完了。
您可以使用我的第一种方法,或者您的GenerateRandomContact应该返回IEnumerable of Contact,但是存在问题,您想要在随机创建上需要多少元素,或者您没有将数量指定为以下
public IEnumerable<Contact> GenerateRandomContact()
{
var random = new Random(Environment.TickCount);
for (int i = 0; i < 100; i++)
{
yield return new Contact
{
Name = $"Name_{random.Next()}"
};
}
}
或您传递参数
但现在整个问题是,如果你想把你的方法称为Enumerable.Generate,这是不可能的,你不能在静态类上有扩展方法,因为扩展方法只适用于可实例化的类型和静态类无法实例化。
你的电话应该是
IEnumerable<Contact> contacts = new List<Contact>(){....}
//where contacts is an instance of type
contacts.Generate
即使你想要这种语法
contacts.Generate(GenerateRandomContact).Take(5);
你的扩展方法应该接受一个函数,但在这里我依赖于之前的GenerateRandomContact(),其中我放了100个随机联系人
public static class Extension
{
public static IEnumerable<T> Generate<T>(this IEnumerable<T> elements, Func<IEnumerable<T>> func)
{
if (func != null)
{
return func();
}
return Enumerable.Empty<T>();
}
}
恕我直言,请尝试考虑传递您想要的金额。你的语法会有所改变
class Program
{
static void Main(string[] args)
{
IEnumerable<Contact> contacts = new List<Contact>()
{
new Contact
{
Name = "Name1"
},
new Contact
{
Name = "Name2"
}
}; //load your methods from the database or create them here
var res = contacts.Generate(GenerateRandomContact, 5);
Console.ReadLine();
}
static IEnumerable<Contact> GenerateRandomContact(int amount)
{
var random = new Random(Environment.TickCount);
for (int i = 0; i < amount; i++)
{
yield return new Contact
{
Name = $"Name_{random.Next()}"
};
}
}
}
public class Contact
{
public string Name { get; set; }
}
public static class Extension
{
public static IEnumerable<T> Generate<T>(this IEnumerable<T> elements, Func<int, IEnumerable<T>> func, int amount)
{
if (func != null)
{
return func(amount);
}
return Enumerable.Empty<T>();
}
}
}