【问题标题】:Class specific method as parameter类特定方法作为参数
【发布时间】:2015-01-06 09:47:01
【问题描述】:

我的主要目标是尝试了解 C# 的工作原理。

我想做这样的事情:

static class MagicalClass
{
    public static List<T>   DoMagic<T>(List<T> sourceList, METHODPOINTER methodOfT)
    {
        return (list.OrderBy(obj => obj.methodOfT())).ToList();
    }
}

如果我的主要目标(如上面描述的)无法达到,我可以做一些事情,比如添加List&lt;T&gt; DoMagic&lt;T&gt;(List&lt;T&gt; sourceList, METHODPOINTER methodOfT) where T : SomeInterface

我需要将 METHODPOINTER 替换为 Func&lt;T&gt; 之类的东西,但特定于某个类

例如:

class SomeClass
{
    private static int id = 0;
    private int currId = 0;
    SomeClass() { currId = id++; }
    public int doStuff() { return (currId); }
    public int doOtherStuff() { return (currId + id); }
}


class AnotherClass
{
    String proceedLogic()
    {
        List<SomeClass>  aList = new List<SomeClass>();
        aList.Add(new SomeClass());
        aList.Add(new SomeClass());
        var sortedList = MagicalClass.DoMagic<SomeClass>(aList, SomeClass.doStuff); // this is my goal
        List<SomeClass> sameSortedList = aList.OrderBy(x => x.doStuff()).ToList(); // would be the same thing
    }
}

我很确定这是可能的,C# 可以评估它,甚至扣除&lt;SomeClass&gt; 部分。 我想我只需要知道语法是什么以及涉及到什么系统类。

提前感谢您的回答。

【问题讨论】:

  • 您是否尝试过将方法设为静态?
  • 就我所经历的 Func<...> 无法将其实例限制在特定的类范围/方法中,我可以对所有内容进行硬编码,但这不是我的目标。

标签: c# generics methods delegates windows-runtime


【解决方案1】:

Func&lt;T&gt; 实际上是一系列带有多个参数的泛型类。

考虑Func&lt;T&gt;的最简单方法如下:

  • Func&lt;TResult&gt; 是一个没有参数的方法,返回类型为 TResult
  • Func&lt;T, TResult&gt; 是一个具有 1 个 T 类型参数和一个 返回类型为TResult
  • Func&lt;T,V,TResult&gt; 是一个具有 T 和 V 类型的 2 个参数的方法,并且 返回类型为TResult

所以实际上,你可以传递任何方法指针,只要它的签名是一个定义明确的委托。

【讨论】:

  • 感谢您的提醒,与此同时,就我所体验的 Func<...> 不允许我将其实例限制在特定的类范围内
  • 然后定义一个只用于类的委托。但是既然它是一个特定的接口实现,为什么还要麻烦传递方法——你知道接口——直接调用方法?
  • 我真的很想定义一个仅用于类的委托,但似乎我不知道限制它的语法。 public delegate void SomeDelegate() 之类的东西对我不起作用。这是关于你在哪里申报的协议吗?如前所述,我想避免通过接口解决方案,我真的想避免对调用进行硬编码。
【解决方案2】:

通过使用 T 和泛型参数 TProp,该方法可以推断用于排序依据的函数的列表类型和返回类型。

OrderBy 期望 Func&lt;SomeClass,???&gt; 进行排序。 TProp 提供 ???输入。

我还包含了一个 doStaticStuff 方法,如果你有一个已经匹配预期签名的方法,你可以看到它是如何工作的。

static class MagicalClass
{
    public static List<T> DoMagic<T, TProp>(List<T> sourceList, Func<T, TProp> methodOfT)
    {
        return (sourceList.OrderBy(methodOfT)).ToList();
    }
}

public class SomeClass
{
    private static int id = 0;
    private int currId = 0;
    public SomeClass() { currId = id++; }
    public int doStuff() { return (currId); }
    public int doOtherStuff() { return (currId + id); }
}

public static int doStaticStuff(SomeClass item)
{
    return item.doOtherStuff();
}

public class AnotherClass
{
    public void proceedLogic()
    {
        List<SomeClass> aList = new List<SomeClass>();
        aList.Add(new SomeClass());
        aList.Add(new SomeClass());

        var sortedList1 = MagicalClass.DoMagic(aList, x => x.doStuff()); // pass in a Func<SomeClass,int> for OrderBy
        List<SomeClass> sameSortedList = aList.OrderBy(x => x.doStuff()).ToList(); // would be the same thing

        var sortedList2 = MagicalClass.DoMagic(aList, doStaticStuff); // pass in a function that matches the expected signature
    }
}

【讨论】:

  • 感谢对 OrderBy() 期望的启发。那就是说您达到了我想避免的程度;这样做,我也看到我还不够清楚。能够建立我想要的“概念”的后果是不可能使用“SomeClass”范围之外的任何其他方法;而public static int doStaticStuff(SomeClass item) 不在范围内。
  • 据我所知,在编译时没有办法做到这一点。我并不是说这是一个好主意,但是您可以接受 Expression&lt;Func&lt;T,TProp&gt;&gt; 类型的参数,如果它引用了一个不在您的类中的方法,则抛出异常(如果允许该表达式,您将 .Compile()然后将该结果传递给您的 OrderBy)。
猜你喜欢
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多