C # оператор перегрузки == и! = - PullRequest
3 голосов
/ 02 февраля 2010

У меня проблемы с получением нужного поведения из этих нескольких классов и интерфейсов.

Вот моя проблема,

//Inside a Unit Test that has access to internal methods and properties

INode  firstNode, secondNode;

INodeId  id = new NodeId (4);

first = new Node (id, "node");
second = new Node (id, "node");

Assert.IsTrue (first == second);

Утверждение выше не выполнено, потому что оно похоже на метод equals класса объекта вместо перегруженного оператора в классах Node и NodeId.

Если у вас есть какие-либо предложения о том, как мне добиться желаемого поведения, это было бы замечательно.

Вот часть платформы, над которой я работаю:

public interface IIdentifier<T> where T : class
{
    TKeyDataType GetKey<TKeyDataType> ();

    bool Equals (IIdentifier<T> obj;
}

public interface INode
{
    string name
    {
        get;
    }

    INodeId id
    {
        get;
    }
}

public interface INodeId : IIdentifier<INode>
{
}

public class Node : INode
{
    internal Node(INodeId  id, string name)
    { 
       //Work
    }

    public static bool operator == (Node n1, Node n2)
    {
        return n1.equals(n2);
    }

    public static bool operator != (Node n1, Node n2)
    {
        return !n1.equals(n2);
    }

    public bool Equals (INode  node)
    {
        return this.name == node.name &&
               this.id = node.id;
    }

    #region INode Properties

    }

public class NodeId : INodeId
{

    internal NodeId(int id)
    { 
       //Work
    }

    public static bool operator == (NodeId  n1, NodeId  n2)
    {
        return n1.equals(n2);
    }

    public static bool operator != (NodeId  n1, NodeId  n2)
    {
        return !n1.equals(n2);
    }

    public override bool Equals (object obj)
    {
        return this.Equals ((IIdentifier<INode>) obj);
    }

    public bool Equals (IIdentifier<INode> obj)
    {
        return obj.GetKey<int>() ==  this.GetKey<int>();
    }

    public TKeyDataType GetKey<TKeyDataType> ()
    {
        return (TKeyDataType) Convert.ChangeType (
            m_id,
            typeof (TKeyDataType),
            CultureInfo.InvariantCulture);
    }


    private int m_id;

}

Ответы [ 3 ]

6 голосов
/ 02 февраля 2010

Операторские перегрузки разрешаются во время компиляции на основе объявленных типов операндов, а не фактического типа объектов во время выполнения. Альтернативный способ сказать, что перегрузки операторов не являются виртуальными. Таким образом, сравнение, которое вы делаете выше, это INode.operator==, а не Node.operator==. Поскольку INode.operator== не определено, перегрузка разрешается до Object.operator==, что просто делает сравнение ссылок.

Не очень хороший способ обойти это. Самое правильное, что нужно сделать, это использовать Equals() вместо == везде, где операнды могут быть объектами. Если вам действительно очень нужна ложная перегрузка виртуального оператора, вы должны определить operator == в корневом базовом классе, от которого наследуются ваши объекты, и вызвать этот вызов перегрузки Equals. Обратите внимание, однако, что это не будет работать для интерфейсов, что у вас есть.

1 голос
/ 02 февраля 2010

Я думаю, что вам может потребоваться переопределить Equals (объект) в Node, как вы это сделали в NodeId. Итак:

public override bool Equals (object obj)
{
    if (obj is Node)
    {
        return this.Equals(obj as Node);
    }
    return false;
}

// your code (modified to take a Node instead of an INode)
public bool Equals (Node  node)
{
    return this.name == node.name &&
           this.id = node.id;
}
0 голосов
/ 02 февраля 2010

он использует == из объекта, потому что firstNode и secondNode не имеют типа Node, они имеют тип INode. Компилятор не распознает базовые типы.

Поскольку вы не можете перегрузить оператор в интерфейсе, вам лучше всего переписать код, чтобы он не использовал интерфейс INode.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...