How to get attribute of a generic type object?

3

I'm having trouble retrieving an object to get a specific attribute.

I want to override the Equals method in my class, to compare if the title of the objects are identical. In this case, it does not matter if the type and the other attributes are different. I just want to compare if the Title attribute of both are equal.

My code looks like this:

namespace Kitty.Core.Blocks
{
    class Block<T>
    {
        public string Title { get; private set; }
        public T Contents { get; private set; }

        public Block(string title, T contents)
        {
            this.Title = title;
            this.Contents = contents;
        }

        public override bool Equals(object obj)
        {
            Block<?> other = obj; // ?



            return string.Equals(this.Title, other.Title);
        }
    }
}

The problem is this:

public override bool Equals(object obj)
{
    Block<?> other = obj; // Como recupero "obj"?


    return string.Equals(this.Title, other.Title);
}

I tried this way:

Block<?> other = (Block<?>) obj;

And so:

Block other = (Block) obj;

But I'm forced to specify the type:

  

Using the generic type ' Block<T> ' requires 1 type arguments.

As I'm overwriting, it's no use changing the method's signature and changing object to the same class name.

So, how can I retrieve this obj , keeping its generic type (which I do not know what it will be) to compare only the Title attribute of both?

    
asked by anonymous 18.04.2016 / 04:55

1 answer

4

I do not know if there are any goals that I did not understand, but just put the normal generic and treat the object as if it were the type you want. If it is not, it will receive null and need to handle this:

public override bool Equals(object obj) {
    Block<T> other = obj as Block<T>;
    if (other == null) return false;
    return Title == other.Title;
}

Obviously you have other ways to do the same.

See working on dotNetFiddle .

Note that you can not compare Block<string> to Block<List<string>> and expect them to be equal. If even the object type is different, there is no way to be the same. When trying to cast a cast on the received object, it will fail and the result will be null, after all you can not transform a Block<List<string>> into a Block<string> , they are structurally different. Even if it has one field ( Title ) equal, the other is not even of the same type. You can only give false .

You might want to throw an exception instead of returning false . I do not like this solution, it would be less idiomatic than in Java (which abuses exceptions).

You could use a normal cast ( (tipo) ) but it could generate an exception, I do not think it is desirable. Simple cast should only be used when you are sure that it will not fail, which is not the case. Even if you prefer it, which I consider a mistake, and prefer that this method throws an exception, which I also find inappropriate, the exception should be another one, so it would be better to catch the cast exception and cast one of ArgumentException .

Some considerations:

  • In C # what is being called the attribute is usually called the field , since attribute is the name of another language mechanism.
  • In C # it is rarer to abuse the namespace separation, which is something quite different from Java packages. Each point creates a new namespace and usually only creates a new one when it is actually used and makes sense, we do not usually use the dot just to separate the word.
  • When you create a specialized% share, you almost always want to create a% specialized share as well.
  • It would probably be best to create (or only) the equality operator ( Equals() ) as well. In C # the GetHashCode() method is not used as much, since the language allows to have specialized operators. This can be seen in the example I made preferring the operator instead of the method.
18.04.2016 / 05:18