简体   繁体   English

C#中的接收器中的有效返回值变为null

[英]Valid return value becomes null in receiver in C#

I'm just getting into C#, so forgive me if this is a basic question. 我刚刚进入C#,如果这是一个基本问题,请原谅我。 I'm building a WPF application using .NET 4.0 and VS 2010. 我正在使用.NET 4.0和VS 2010构建WPF应用程序。

I have a class in which I'm storing a List of objects; 我有一个类,我在其中存储一个对象List ; the objects have a Point object as a field. 对象将Point对象作为字段。 One of the method returns the object in list at a specific location: 其中一个方法返回列表中特定位置的对象:

public Marker markerAtLocation(Point location) {
    foreach (Marker nextMarker in Markers)
        if (nextMarker.Location().Equals(location))
            return nextMarker;
    return null;
}

Setting breakpoints and using Console.WriteLine I've confirmed that nextMarker is valid at the return. 设置断点并使用Console.WriteLine我已经确认nextMarker在返回时有效。 However, in the receiver the object is always null : 但是,在接收器中,对象始终为null

Marker top = markerAtLocation(new Point(location.X, location.Y + 1));
if (top == null)
    Console.WriteLine("Top is null");
else
    Console.WriteLine("Top is " + top.ToString());
Marker bottom = markerAtLocation(new Point(location.X, location.Y - 1));
if ((bottom != null) && (bottom.player == otherPlayerType()) && (top != null) && (top.player == otherPlayerType()))
    return true;

I don't know what's going wrong here… 我不知道这里出了什么问题......

Note that I'd initially thought it was an issue with .NET's Point struct using double values. 请注意,我最初认为这是.NET的Point结构使用double值的问题。 I know in my app the location values will always be integers so I didn't use the .NET Point and created my own: 我知道在我的应用程序中,位置值将始终为整数,因此我没有使用.NET Point并创建了自己的:

class Point {
    public int X, Y;

    public Point(int X, int Y) {
        this.X = X;
        this.Y = Y;
    }

    public bool Equals(Point anotherPoint) {
        return ((anotherPoint.X == X) && (anotherPoint.Y == Y));
    }
}

I'd appreciate any help! 我很感激任何帮助!

Edit: In response to pbirkoff: 编辑:回应pbirkoff:

class Grid {
    public List<Marker> Markers;

    public Grid() {
        Markers = new List<Marker>();
    }

    public Grid(List<Marker> markers) {
        this.Markers = markers;
    }

    public void addMarker(Marker newMarker) {
        Markers.Add(newMarker);
    }

I've tried the solutions below to the best of my ability but none of them have helped. 我尽我所能尝试了以下解决方案,但没有人帮助过。 I'm including a link to the project itself as well as the problem I'm attempting to solve. 我要包含项目本身的链接以及我试图解决的问题。

Project: http://dl.dropbox.com/u/7828009/ACSLPetteia.zip 项目: http//dl.dropbox.com/u/7828009/ACSLPetteia.zip
Problem: http://wcipeg.com/etc/ACSL/VOL%2030/ACSL%20Petteia_sr_3.doc 问题: http//wcipeg.com/etc/ACSL/VOL%2030/ACSL%20Petteia_sr_3.doc

Thanks in advance! 提前致谢!

I implemented your code as succinctly as I could, making some mocks where appropriate (code below), and I cannot get it to fail. 我尽可能简洁地实现了你的代码,在适当的地方做了一些模拟(下面的代码),我不能让它失败。 What am I missing in my code sample: 我的代码示例中缺少什么:

class Program
{
    static void Main(string[] args)
    {
        LoadMarkers();
        var location = new Point(45, 45);
        Marker top = markerAtLocation(new Point(location.X, location.Y + 1));
        if (top == null)
            Console.WriteLine("Top is null");
        else
            Console.WriteLine("Top is " + top.ToString());
        Marker bottom = markerAtLocation(new Point(location.X, location.Y - 1));

    }
    public static List<Marker> Markers = new List<Marker>();
    private static void LoadMarkers()
    {
        for (var q = 0; q < 50; q++)
            for (var w = 0; w < 50; w++)
                Markers.Add(new Marker(q, w));
    }
    public static Marker markerAtLocation(Point location)
    {
        foreach (Marker nextMarker in Markers)
            if (nextMarker.Location().Equals(location))
                return nextMarker;
        return null;
    }
}
class Marker
{
    private Point _loc;
    public Marker(int x, int y) { _loc = new Point(x, y); }
    public Point Location() { return _loc; }
}
class Point
{
    public int X, Y;
    public Point(int X, int Y)
    {
        this.X = X;
        this.Y = Y;
    }
    public bool Equals(Point anotherPoint)
    {
        return ((anotherPoint.X == X) && (anotherPoint.Y == Y));
    }
}

Could be related to curly braces (much more readable when you use them IMHO), though that's probably not very likely. 可能与花括号有关(当你使用它们时更可读)恕我直言,虽然这可能不太可能。 What if you declare a local variable to the function as a holder and return the stored value of that variable? 如果将一个局部变量声明为函数作为持有者并返回该变量的存储值,该怎么办? Does this solve the problem or does it still exhibit the same behavior? 这是解决问题还是仍然表现出相同的行为? For example: 例如:

public Marker markerAtLocation(Point location) {
    Marker returnMarker = null;
    foreach (Marker nextMarker in Markers) {
       if (nextMarker.Location().Equals(location)) {
           returnMarker = nextMarker;
           break;
       } // end if
    } // end foreach
    return returnMarker;
} // end function

I'd first start by changing the names of your classes. 我首先要改变你的课程名称。 Namespaces would normally take care of any conflicts, but the WPF point, being defined in System.Windows is most likely going to cause issues when trying to create your Point in a WPF Window class, which I'm guessing is where your receiver code is located. 命名空间通常会处理任何冲突,但是在System.Windows中定义的WPF点很可能在尝试在WPF窗口类中创建Point时会引起问题,我猜测你的接收器代码是位于。 The reason I say this is that by default you get a "using System.Windows;" 我说这个的原因是默认情况下你会得到一个“使用System.Windows;” line at the top of the auto-generated Window classes VS creates. VS创建的自动生成的Window类顶部的行。

Since everything derives from object, you'll want to override the bool Equals(object o) function as well, since this will help you catch the issue where it's comparing against a System.Windows.Point instead of your Point. 由于所有内容都来自于object,因此您也希望覆盖bool Equals(object o)函数,因为这将帮助您捕获与System.Windows.Point而不是Point进行比较的问题。

I think if you change the name of your class to IntPoint, you might find that the "new Point" in your receive code might not get refactored to "new IntPoint" since it could be resolving to System.Windows.Point. 我想如果你将类的名称更改为IntPoint,你可能会发现接收代码中的“新点”可能不会被重构为“new IntPoint”,因为它可能会解析为System.Windows.Point。

Same goes for using Grid as a name. 使用Grid作为名称也是如此。 I try to stick to the convention of not using type names that match .NET type names to avoid odd conflicts. 我试图坚持不使用匹配.NET类型名称的类型名称的约定,以避免奇怪的冲突。

So to sum up, change your class to the following: 总而言之,将您的课程更改为以下内容:

class IntPoint {
    public int X { get; set; }
    public int Y { get; set; }

    public IntPoint(int X, int Y) {
        this.X = X;
        this.Y = Y;
    }

    public override bool Equals(object obj)
    {
        if (obj is IntPoint) return Equals(obj as IntPoint);
        return base.Equals(obj);
    }

    public bool Equals(IntPoint anotherPoint) {
        return ((anotherPoint.X == X) && (anotherPoint.Y == Y));
    }
}

I also changed your public fields to public properties using the shorthand default get/set syntax. 我还使用简写的默认get / set语法将公共字段更改为公共属性。 I won't go into the details of properties vs fields, but it'd be good for you to search the web for .net properties vs public fields. 我不会详细介绍属性与字段,但是在网上搜索.net属性与公共字段是有好处的。 Part of the reasoning has to do with how Binding works. 部分原因与Binding的工作原理有关。 .Net allows you to bind to properties, but if you tried to bind to one of the fields, I believe it will fail to find them. .Net允许您绑定到属性,但如果您尝试绑定到其中一个字段,我相信它将无法找到它们。

Post back if you make these changes and it's still not working. 如果您进行这些更改并且仍然无法正常工作,请回发。

Are you like 100% positive that markerAtLocation is returning a non null Marker. 你是否100%肯定markerAocation正在返回非空标记。 In debug you see that line called?? 在调试中你看到那行调用? No you don't see it call that line because the way you have it structured debug does not have a line to stop on to see it "return nextMarker(). You have 3 levels of logic going on here with no {}. Are you sure your code is running like you expect? 不,你没有看到它调用那条线,因为你有结构调试的方式没有一行停下来看它“返回nextMarker()。你有3级逻辑在这里没有{}。是你确定你的代码像你期望的那样运行吗?

    foreach (Marker nextMarker in Markers)
    if (nextMarker.Location().Equals(location))
        return nextMarker;
        return null;

What I suspect is happening the loop only goes to the second line. 我怀疑正在发生的循环只进入第二行。 On the last and only the last it proceeds to return nextMarker and it is true only if the match was on the last line. 在最后一次,只有最后一次,它继续返回nextMarker,只有当匹配在最后一行时才是真的。 Clean up your logic - it cannot hurt. 清理你的逻辑 - 它不会伤害你。

    foreach (Marker nextMarker in Markers)
    {
        if (nextMarker.Location().Equals(location))
        {
            return nextMarker;
        }
    }
    return null;

I think that we'd need more information (as Jon requested) to ascertain exactly what is wrong here. 我认为我们需要更多信息(如Jon所要求的)来确定这里到底出了什么问题。

Perhaps you're using a static function and refering to non-static items such as your public class members. 也许您正在使用静态函数并引用非静态项目,例如您的公共类成员。 This would still compile and run although the non-static variables wouldn't have been initialised or set before they are used. 这仍然可以编译和运行,尽管非静态变量在使用之前不会被初始化或设置。

Always best to implement public class variables as properties eg public List<Marker> Markers{get;set;} instead of public List<Marker> Markers . 总是最好将公共类变量实现为属性,例如public List<Marker> Markers{get;set;}而不是public List<Marker> Markers The same would go for X and Y in your Point class. 您的Point类中的X和Y也是如此。

My gut feeling is that some of your class instances are no longer in scope or because they are public variables it is possible that they have been overwritten - try defining them volatile - by the time that you come to refer to them. 我的直觉是,你的一些类实例不再在范围内,或者因为它们是公共变量,它们可能被覆盖 - 尝试将它们定义为volatile - 在你引用它们的时候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM