Can I use class and struct at the same time?

Asked

Viewed 291 times

8

I have a variable "Address", however, it is composed by "Street", "Number" etc. The way I did below is the best to be done? With class and struct at the same time? Or is there something better and simpler to be done?

public struct Endereco
{
    public string Rua { get; set; }
    public string Numero { get; set; }
    public string Bairro { get; set; }
    public string Cidade { get; set; }
}

public class Cliente
{
    public int idCliente { get; set; }
    public string Nome { get; set; }
    public Endereco Endereco_;
}

And here as I call in form:

Cliente cli = new Cliente();
cli.idCliente = int.Parse(txtidCliente.Text);
cli.Nome = txtNome.Text;
cli.Endereco_.Rua = txtRua.Text;
//...etc

2 answers

8


It is not using at the same time, it is making a structure and then a class. There is no problem in general, at least not because there are both. But this case seems to be quite wrong.

The organization is right, but the correct thing would be to have two classes*.

Why can’t you use struct in Endereço?

There are two "impediments".

First she is very big. She will have 4 words (whereas it will not grow in the future). 32-bit architecture is 16 bytes. 64-bit architecture is 32 bytes. Only pointers to text are stored in the structure.

This is a lot of things, it is at the limit of recommended, but can grow, has no ZIP code, may need more things, such as "add-on" or "indication of location". Structures should only have up to 16 bytes. I’ve done some tests and I saw that it gives good results with bigger sizes, but I know what I’m doing and when you want to go over the official recommendation, it’s very nuanced, if you don’t understand everything, it’s best to stay in the recommendation.

The problem is that structures are types per value and they are passed by copy, can be inefficient if it is too large.

Precisely because they are by value people do not understand the semantics well when they change their data.

When you copy data from a variable by value (struct) another object is created, so moving on one does not touch the other. And there is a lot of copying that the person does not even realize it occurs. In the case of types by reference (class) the copy is of the pointer and not of the object itself, so it is always the same object. Moved it, all references to it will see the modification. Marco Giovanni’s answer shows how this occurs.

Structures must be immutable, or change everything and you get a new object or change nothing. This does not seem to be the case Endereco. The data can be changed independently. In fact there is no mechanism protecting it.

Have you ever paid attention to the C# guys who are structs? All things small and indivisible.

There are exceptions

If you know very well what you are doing can abuse the structures to gain performance relieve the Garbage Collector. This site you are using now does a lot of this in your software. In the cases that need to avoid copying it uses the ref. What alias, with new features of C# 7, will tend to be used more and more in systems where performance and memory management matters more.

The new features that are coming in the next versions will help ensure immutability, even if you can do it now.

Again, everything can if you know all the implications of its use.

Note that some classes prefer to be immutable. String is the most obvious case. There are those who say that everything should be immutable and this is done in other languages. It has its disadvantages there.

To understand better read What’s the difference between Struct and Class?.

Eric Lippert talks in detail and few people have more authority over it than him. The example he sets is great:

struct Mutable {
    private int x;
    public int Mutate() {
        this.x = this.x + 1;
        return this.x;
    }
}

class Test {
    public readonly Mutable m = new Mutable();
    static void Main(string[] args) {
        Test t = new Test();
        System.Console.WriteLine(t.m.Mutate());
        System.Console.WriteLine(t.m.Mutate());
        System.Console.WriteLine(t.m.Mutate());
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

What does he do? (This is a quiz, answer before seeing the above execution)

  1. Prints 1, 2, 3 - why m is readonly, although this applies only to the variable and not its members.

  2. Prints 0, 0, 0 - why m is readonly, x cannot be changed and always has default value 0.

  3. It throws an exception when so much change the member’s state, which it believes to be readonly (is not declared, but thinks it is transferred from variable to member.

  4. Prints 1, 1, 1. Because as the data is copied on each access, it does not use the previous state. When using t.m, you take a copy of what is on m. m is immutable (by readonly), but your copy is not.

There may be problems with this approach, even if I use a class, but I won’t talk because it’s not the focus of the question. You may also have other problems with the code. But there’s no context, it’s hard to say.

*Note that I haven’t even analyzed whether the address should actually be a separate entity. This could be an error in your case. I have no way to evaluate this.

  • Thank you so much for the reply. And I will read the links you posted during the text. Thank you!

6

You can only class in this case as the data manipulation you will be manipulating only the memory address:

Difference between class and struct:

Class

public class Endereco
{
    public string Rua { get; set; }
}

Endereco ex1 = new Endereco(){Rua = "rua xxx"};
Endereco ex2 = ex1;
ex2.Rua = "Rua yyy"

//Ambos vão estar com o mesmo valor, pois ex2, faz apenas referencia na memória de ex1
//ex1.Rua == "Rua yyy"
//ex2.Rua == "Rua yyy"

Struct

public struct Endereco
{
    public string Rua { get; set; }
}

Endereco ex1 = new Endereco(){Rua = "rua xxx"};
Endereco ex2 = ex1;
ex2.Rua = "Rua yyy"

//Não vão estar com o mesmo valor
//ex1.Rua == "Rua xxx"
//ex2.Rua == "Rua yyy"

When is used struct?

Struct is usually used in primitive types and when you need to create a structure to interoperability with another language.

In this reply you find a very detailed explanation of the differences.

  • 3

    You answered with a clear example and managed to better understand the differences between the two. And I will read the text of the link too. Thank you very much!

Browser other questions tagged

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