Допустимое возвращаемое значение становится нулевым в получателе в C # - PullRequest
3 голосов
/ 02 ноября 2011

Я только вхожу в C #, так что простите, если это основной вопрос. Я создаю приложение WPF с использованием .NET 4.0 и VS 2010.

У меня есть класс, в котором я храню List объектов; объекты имеют объект Point в качестве поля. Один из методов возвращает объект в списке в определенном месте:

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

Установка точек останова и использование Console.WriteLine Я подтвердил, что nextMarker действителен при возврате. Однако в получателе объект всегда 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;

Я не знаю, что здесь происходит не так ...

Обратите внимание, что изначально я думал, что это проблема структуры Point .NET, использующей двойные значения. Я знаю, что в моем приложении значения местоположения всегда будут целыми числами, поэтому я не использовал .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));
    }
}

Буду признателен за любую помощь!

Редактировать: В ответ на 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);
    }

Я испробовал приведенные ниже решения в меру своих возможностей, но никто из них не помог. Я включаю ссылку на сам проект, а также проблему, которую пытаюсь решить.

Проект: http://dl.dropbox.com/u/7828009/ACSLPetteia.zip
Проблема: http://wcipeg.com/etc/ACSL/VOL%2030/ACSL%20Petteia_sr_3.doc

Заранее спасибо!

Ответы [ 5 ]

1 голос
/ 02 ноября 2011

Я реализовал ваш код настолько кратко, насколько мог, выполняя некоторые проверки, где это уместно (код ниже), и я не могу заставить его потерпеть неудачу. Чего мне не хватает в моем примере кода:

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));
    }
}
0 голосов
/ 03 ноября 2011

Я думаю, что нам нужно больше информации (как просил Джон), чтобы точно выяснить, что здесь не так.

Возможно, вы используете статическую функцию и ссылаетесь на нестатические элементы, такие как члены вашего открытого класса.Это все равно будет компилироваться и запускаться, хотя нестатические переменные не были бы инициализированы или установлены до их использования.

Всегда лучше всего реализовать переменные открытого класса в качестве свойств, например, public List<Marker> Markers{get;set;} вместо public List<Marker> Markers.То же самое касается X и Y в вашем классе Point.

Мне кажется, что некоторые из ваших экземпляров классов больше не находятся в области видимости или потому, что они являются общедоступными переменными, возможно, они были перезаписаны - попробуйте определить их volatile - к тому времени, когда вы придете кобратитесь к ним.

0 голосов
/ 02 ноября 2011

Вы на 100% уверены, что markerAtLocation возвращает ненулевой маркер. В отладке вы видите, что строка называется ?? Нет, вы не видите, чтобы она вызывала эту строку, потому что, как у вас это структурировано, отладка не имеет строки, на которой можно остановиться, чтобы увидеть ее "return nextMarker (). Здесь у вас есть 3 уровня логики, без {}. Вы уверены, что ваш код работает так, как вы ожидаете?

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

То, что я подозреваю, происходит, петля переходит только на вторую строку. В последнем и только последнем случае он продолжает возвращать nextMarker, и это верно только в том случае, если совпадение было в последней строке. Очисти свою логику - это не повредит.

    foreach (Marker nextMarker in Markers)
    {
        if (nextMarker.Location().Equals(location))
        {
            return nextMarker;
        }
    }
    return null;
0 голосов
/ 02 ноября 2011

Я бы сначала начал с изменения названий ваших классов.Пространства имен обычно решают любые конфликты, но точка WPF, определяемая в System.Windows, скорее всего, вызовет проблемы при попытке создать свою точку в классе окна WPF, что, как я предполагаю, является тем, где находится код получателя.расположен.Причина, по которой я говорю это, заключается в том, что по умолчанию вы получаете «using System.Windows;»Вверху автоматически сгенерированных оконных классов создается VS.

Поскольку все происходит от объекта, вы также захотите переопределить функцию bool Equals (объект o), так как это поможет вам пойматьпроблема, при которой он сравнивается с System.Windows.Point вместо вашей точки.

Я думаю, что если вы измените имя вашего класса на IntPoint, вы можете обнаружить, что «новая точка» в вашем коде получения может неполучить рефакторинг для «нового IntPoint», поскольку он может быть преобразован в System.Windows.Point.

То же самое касается использования Grid в качестве имени.Я стараюсь придерживаться соглашения об использовании имен типов, которые не совпадают с именами типов .NET, чтобы избежать нечетных конфликтов.

Итак, чтобы подвести итог, измените свой класс на следующее:

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

Я также изменил ваши открытые поля на открытые свойства, используя сокращенный стандартный синтаксис get / set.Я не буду вдаваться в подробности свойств по сравнению с полями, но было бы хорошо, если бы вы искали в Интернете свойства .net по сравнению с открытыми полями.Часть рассуждений связана с тем, как работает Binding..Net позволяет вам связывать со свойствами, но если вы попытались связать одно из полей, я думаю, что он не сможет их найти.

Отправьте сообщение обратно, если вы внесете эти изменения, и оно все еще не работает.

0 голосов
/ 02 ноября 2011

Может быть связано с фигурными скобками (гораздо более читабельно при их использовании, ИМХО), хотя это, вероятно, не очень вероятно. Что если вы объявите локальную переменную для функции в качестве держателя и вернете сохраненное значение этой переменной? Это решает проблему или все еще демонстрирует такое же поведение? Например:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...