如何指定列表选择方法?

发布于 2024-10-05 07:13:16 字数 1143 浏览 2 评论 0 原文

我有一个计算列表的方法。在算法中的某些点,需要从列表中选择单个元素。选择哪个元素并不重要,但我想将其留给用户来决定。

现在,我添加了一个扩展方法 IList.Random(),它只接受一个随机元素。 .First() 也同样有效。假设我想让用户选择使用哪种方法,或者可能是一种完全不同的方法,那会是什么样子?

我正在考虑使用选项有限的枚举,然后我可以将每个调用包装在一个开关中并调用适当的函数。 但也许某种 lambda 函数会更合适?

此方法需要在两个不同的地方使用,一次在 List 上,一次在 List 上。我想对两者使用相同的方法。


这不是 GUI 应用程序。我正在尝试决定如何设计 API。

具体来说,我想要一个像

public Func<IList<T>, T> SelectElement = list => list.First();

Which 这样的字段,然后在方法中使用,

 public string Reverse(string pattern, IList<object> args = null, IDictionary<string, object> kwargs = null)

但通用字段是不可能的。所以我正在寻找替代解决方案。一种方法是使 SelectElement 方法成为 Reverse() 的参数,然后我可以使其通用......但我希望将其保留在类级别以实现可重用性。如果我可以帮助的话,不想再向该函数传递任何参数。

编辑: 完整源代码

I've got a method that computes a list. At certain points in the algorithm a single element from the list needs to be chosen. It doesn't really matter which element is chosen, but I'd like to leave it up to the user to decide.

Right now, I've added an extension method IList<T>.Random() which simply takes a random element. .First() would have worked equally as well. Supposing I want to let the user pick which method is used, or perhaps an entirely different method, how would that look?

I was thinking about using an enum with limited options, and then I could wrap each of these calls in a switch and call the appropriate function. But maybe some sort of lambda function would be more appropriate?

This method needs to be used in two different places, once on a List<char> and once on a List<string>. I want to use the same method for both.


This isn't a GUI app. I'm trying to decide how to design the API.

Specifically, I want to have a field like

public Func<IList<T>, T> SelectElement = list => list.First();

Which would then be used in the method,

 public string Reverse(string pattern, IList<object> args = null, IDictionary<string, object> kwargs = null)

But generic fields aren't possible. So I'm looking for an alternative solution. One would be to make the SelectElement method an argument to Reverse(), then I could make it generic... but I was hoping to keep it at a class-level for re-usability. Don't want to pass any more args to the function if I can help it.

Edit: full source code

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

◇流星雨 2024-10-12 07:13:16

这个怎么样:


    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);
        }
    }

how about this:


    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);
        }
    }
百思不得你姐 2024-10-12 07:13:16

这是我使用通用方法组合而成的一个非常基本的示例,该方法采用 Func, 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);
        }
    }
}

如果您想限制用户的选择,您可以遵循枚举的路线并将此方法设为私有方法,然后有一种方法将枚举转换为适当的方法选择器委托传递给底层私有方法。

Here's an extremely basic example I put together using a generic method that takes in a Func<IEnumerable<T>, T> for selecting an item from the list and then returns the result. I've done a few examples of how to call it:

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);
        }
    }
}

If you want to limit the choices a user has you could follow the route of an enum and make this method a private method and then have a way to convert the enum to the appropriate selector delegate to pass to the underlying private method.

给妤﹃绝世温柔 2024-10-12 07:13:16
public Func<IList<object>, object> SelectElement = list => list.First();

private T _S<T>(IEnumerable<T> list)
{
    return (T)SelectElement(list.Cast<object>().ToList());
}

我可以使匿名方法在对象上工作,从而避免泛型,然后添加一个辅助方法,这就是我实际用来调用它的方法。有点丑,但似乎有用。

public Func<IList<object>, object> SelectElement = list => list.First();

private T _S<T>(IEnumerable<T> list)
{
    return (T)SelectElement(list.Cast<object>().ToList());
}

I can make the anonymous method work on objects, thereby avoiding generics, and then add a helper method which is what I'll actually use to call it. A little ugly, but seems to work.

戈亓 2024-10-12 07:13:16

这适用于字符和字符串。尚未测试其他类型。在我看到 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); 
}

This works for chars and strings. Haven't tested with other types. Built this before I saw Ralph's code, which is practically the same.

LINQPad code:

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); 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文