0

早上好。

让我给你看一些代码:

    //Db is a database of Tag objects, sort of
    Db db;   
    string code = "123";
    var selectedTag = db.Select(new Predicate<Tag>(tag => tag.Code == code));

    //...

    class Db
    {
        //A query method, accepting a Predicate
        public Tag Select(Predicate<Tag> predicate)
        {
            /* Here, using Intellisense, I see that Target property is a Tag object,
              but I can't cast it to Tag! Why??
            */
            var t = predicate.Target as Tag; //Always null!
        }
    }

我基本上有一个简单的Tag对象数据库;当调用者调用Select方法时,我会从中检索Tag对象istance predicate,但实际上我无法让它工作。
在调试中使用 Intellisens,当我在Select方法中时,我清楚地看到它predicate.Target引用了我的Tag对象,但我不知道如何检索它。
有任何想法吗?
谢谢你。

编辑 如果我尝试不安全地投射predicate.TargetTag,这样:

var t = (Tag)predicate.Target;

我得到一个InvalidCastException; 好的,但是Exception消息说我不能将 type 的对象DbTests转换为 type Tag
DbTests是我用于测试目的的 NUnit 测试类(显然...:)。
奇怪的!
编辑 2 行中的错字:

var selectedTag = db.Select(new Predicate<Tag>(tag => tag.Code == code));
4

2 回答 2

1

predicate.Target很可能不是您想要的。

根据MSDN Delegate.Target “获取当前委托调用实例方法的类实例。”。您说您在单元测试类中调用该代码DbTests,因此非常合适。

老实说,您的完整代码看起来是错误的。我想你不想在Select这里有一个方法,而是一个Where方法。a 中的谓词Select没有太大意义,因为 aSelect只是从一个输入值到一个输出值的投影。将谓词传递给此类投影意味着输出值始终为 bool 类型。

于 2012-09-26T13:15:14.370 回答
0

您的Select方法需要一个委托(该委托的类型是 a Predicate<T>,更具体地说是Predicate<Tag>)。该委托指向一个实例和一个方法。您为委托传递的内容是 lambda tag => tag.Code == code。该 lambda 使编译器为此代码生成一个方法。该方法要么包含在调用 的实例中,要么包含在Select新类中。如果生成的方法是static,将没有实例,并且Target将是null。在任何情况下,包含该方法的类都不是Tag(除非调用SelectTag类中;但您没有详细说明)。因此,Target不能成为Tag对象,也永远无法Tag成功转换。

应该select 接收的谓词一个Tag对象。例如:

public Tag Select(Predicate<Tag> predicate)
{
    Tag tag = new Tag();
    bool result = predicate(tag);
    return tag;
}

目前尚不清楚您真正想在其中做什么Select;但Predicate<Tag>只是返回truefalse取决于Tag给它。

更新:

在您的示例中,就好像您这样写:

public class DbTests
{
    public void Test1()
    {
        Db db = new Db();
        Tag selectedTag = db.Select((Predicate<Tag>) TestTag);
    }

    private bool TestTag(Tag tag)
    {
        return tag.Code == "123";
    }
}

上面的代码片段中没有任何Tag实例。

更新:

如果您使用了包含类的实例方法,例如:

public class DbTests
{
    public string code = "123";
    public void Test1()
    {
        Db db = new Db();
        Tag selectedTag = db.Select(tag => tag.Code == code);
    }
}

然后发送到 select 的谓词将有一个与之关联的实例,因此Target不会为空。在上面的代码中,Target将是 typeDbTest 但是,如果您将 Select 调用放在其中TagData(例如DbTests重命名为TagData),那么Target将是 typeTagData并向您显示实例成员TagData,您将获得您在屏幕截图中看到的内容。

Select对于使用Predicate<T>

于 2012-09-26T13:12:48.863 回答