我有一个计算列表的方法。在算法中的某些点处,需要选择列表中的单个元素。选择哪个元素并不重要,但我想让用户自行决定。
现在,我添加了一个扩展方法IList<T>.Random()
,它只是一个随机元素。 .First()
也同样有效。假设我想让用户选择使用哪种方法,或者可能采用完全不同的方法,那会是什么样的?
我正在考虑使用有限选项的枚举,然后我可以将每个调用包装在一个开关中并调用相应的函数。 但是some sort of lambda function可能更合适?
此方法需要在两个不同的位置使用,一次在List<char>
上,一次在List<string>
上。我想对两者使用相同的方法。
这不是GUI应用程序。我正在尝试决定如何设计API。
具体来说,我希望有一个像
这样的字段public Func<IList<T>, T> SelectElement = list => list.First();
然后将在方法中使用
public string Reverse(string pattern, IList<object> args = null, IDictionary<string, object> kwargs = null)
但是通用字段是不可能的。所以我正在寻找替代解决方案。一种方法是将SelectElement
方法作为Reverse()的参数,然后我可以使它成为通用的...但我希望将它保持在类级别以便重用。如果我可以提供帮助,不要再向该函数传递args。
修改: full source code
答案 0 :(得分:2)
怎么样:
public class MyClass
{
public static class C<T>
{
public static Func<IList<T>, T> SelectElement;
}
public int Test(IList<int> list)
{
return C<int>.SelectElement(list);
}
}
static class Program
{
static void Main(string[] args)
{
MyClass.C<char>.SelectElement = xs => xs.First();
MyClass.C<int>.SelectElement = xs => xs.First();
var list = new List<int>(new int[] { 1, 2, 3 });
var c = new MyClass();
var v = c.Test(list);
Console.WriteLine(v);
}
}
答案 1 :(得分:1)
这是我使用泛型方法放在一起的一个非常基本的示例,该方法接受Func<IEnumerable<T>, T>
从列表中选择项目然后返回结果。我已经做了一些如何调用它的例子:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
//Simple list.
var list = new List<int> { 1, 2, 3, 4 };
// Try it with first
var result = DoItemSelect(list, Enumerable.First);
Console.WriteLine(result);
// Try it with last
result = DoItemSelect(list, Enumerable.Last);
Console.WriteLine(result);
// Try it with ElementAt for the second item (index 1) in the list.
result = DoItemSelect(list, enumerable => enumerable.ElementAt(1));
Console.WriteLine(result);
}
public static T DoItemSelect<T>(IEnumerable<T> enumerable, Func<IEnumerable<T>, T> selector)
{
// You can do whatever you method does here, selector is the user specified func for
// how to select from the enumerable. Here I just return the result of selector directly.
return selector(enumerable);
}
}
}
如果要限制用户的选择,可以遵循枚举的路径并使此方法成为私有方法,然后有办法将枚举转换为适当的选择器委托以传递给底层私有方法。
答案 2 :(得分:0)
public Func<IList<object>, object> SelectElement = list => list.First();
private T _S<T>(IEnumerable<T> list)
{
return (T)SelectElement(list.Cast<object>().ToList());
}
我可以让匿名方法处理对象,从而避免使用泛型,然后添加一个帮助方法,这是我实际用来调用它的方法。有点难看,但似乎有效。
答案 3 :(得分:0)
这适用于字符和字符串。没有测试过其他类型。在我看到Ralph的代码之前构建了它,这几乎是相同的。
LINQPad代码:
void Main()
{
var chars = new List<char>();
var strings = new List<string>();
chars.AddRange(new char[] {'1','2','4','7','8','3'});
strings.AddRange(new string[] {"01","02","09","12","28","52"});
chars.Dump();
strings.Dump();
Func<IList<object>, string> SelectFirst = ( list )
=> list.First().ToString();
Func<IList<object>, string> SelectLast = ( list )
=> list.Last().ToString();
Func<IList<object>, string> SelectRandom = ( list )
=> list.ElementAt( new Random().Next(0, list.Count())).ToString();
SelectBy(SelectFirst, strings.Cast<object>().ToList()).Dump();
SelectBy(SelectFirst, chars.Cast<object>().ToList()).Dump();
SelectBy(SelectLast, strings.Cast<object>().ToList()).Dump();
SelectBy(SelectLast, chars.Cast<object>().ToList()).Dump();
SelectBy(SelectRandom, strings.Cast<object>().ToList()).Dump();
SelectBy(SelectRandom, chars.Cast<object>().ToList()).Dump();
}
private string SelectBy(Func<IList<object>, string> func, IList<object> list)
{
return func(list);
}