Method that returns parent class to daughter class

Asked

Viewed 823 times

3

I have the following classes:

public class Pessoa
{
    public int PessoaId { get; set; }
    public string Nome { get; set; }
    public DateTime DataNascimento { get; set; }
}

public class Cliente : Pessoa
{
    public int ClienteId { get; set; }
}
public class Funcionario : Pessoa
{
    public int FuncionarioId { get; set; }
}

I created the following method:

public Pessoa Teste(Pessoa pessoa)
{
    // Bloco lógico
    return pessoa;
}

What I’d like to do now is send a Funcionario or Cliente for the method Teste and get them back with their properties from Pessoa altered.

The problem is that when using:

var func = new Funcionario();
func = Teste(func);

It doesn’t work because my variable func is the type Funcionario, and the return in the method Teste returns a Pessoa. But since Funcionario inherits from Pessoa there’s no way to do that?

  • public Pessoa Teste<Pessoa>(Pessoa pessoa) { } so at least did not give compilation error, but why is the big question!

  • I don’t understand what the point is to decide what’s best for you.

  • ClienteId and FuncionarioId are not necessary. You can remove them from the Models derivatives.

3 answers

5


In a general way Andrew’s answer works, after all if you’re sure you passed a Funcionario for the method then knows what to make a cast of the returned object to Funcionario will work. Without that certainty this would be a danger.

A more "modern" way of doing this is what Gabriel Katakura’s response says. Making a generic method you already guarantee that the type returned will be the type you passed to the method, so you do not need to make a cast and is safer.

public T Teste<T>(T pessoa) where T : Pessoa {
    //faz o que deseja aqui
    return pessoa;
}

Calling for:

var func = new Funcionario();
func = Teste(func); //ele infere, se não fosse possível chamaria Teste<Funcionario>(func)

I put in the Github for future reference.

Note that in this case the compiler will generate a specialized method that will receive an object of some type and return an object of the same type. This is defined by the parameter T which is a super variable of type. I said it receives any object, but it’s not like that. It has a restriction saying that the T must be any kind, as long as he’s a Pessoa, therefore derivative types are valid, others are not. More details are in the question linked above.

When you compile that code it’s like you’ve written:

public Funcionario Teste(Funcionario pessoa) {
    //faz o que deseja aqui
    return pessoa;
}

But you didn’t have to write, that’s the beauty of genericity. The compiler adapts your method to every type you use. It will be defined by the use of the method. This is called client site, or Consumer site.

Obviously you still can’t do anything specific to an object Funcionario or Cliente, can only do things available in Pessoa. If you want to do something specific than just one Funcionario can then must do something with Funcionario even.

  • I do not know if it is worth mentioning, but this advantage of the compiler occurs in the case of C#... some languages the use of Generics is only a Syntactic Sugar to disguise the use of Object with downcast/upcast, as the case of Java, which has Type Erasure. That is, in Java the advantage is only at a high level.

  • Well, taking a look at the links of the linked answer, there is one that explains just that. You can ignore this comment, haha. http://answall.com/questions/10032/quais-as-diff%C3%A7as-between-types-gen%C3%A9ricos-em-c-e-em-java

  • @Gabrielkatakura is no good here, but it’s always useful information. There are some extra details on C#. I simplified it and said that it generates a specific method. This is not quite true, it is smarter than this. It uses the same for all types of reference and avoids the cast for already having the information that everything will work out, after all in certain circumstances the cast is just information for the compiler and does nothing.

3

Just use Generics for this (short answer, I’m out of time, sorry):

public TPessoa Teste<TPessoa>(TPessoa pessoa)
    where TPessoa : Pessoa
{
    return pessoa;
}

1

Have you tried casting?

var func = new Funcionario();
func = (Funcionario)Teste(func);

Since Funcio is also a Person a simple casting should work.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.