0

My class is like:

public class Person
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Nickname{ get; set; }

    public Person GetPersonData()
    {
        return new Person()
        {
            Name = "Chris",
            Surname = "Topher"
        };
    }
}

How can I count elements in GetPersonData() method? I was using GetProperties a bit, but then, when I have some more methods with initialization of others variables, then it does not work as i would like to. I need to get exact number of elements there. Thank you for any help!

Deryl
  • 66
  • 5
  • 4
    What do you mean "initialized fields"? – ProgrammingLlama Aug 28 '18 at 08:07
  • You mean those properties (not fields, btw.) whose value isn´t their default-value? I wonder what the use-case for this is? I can´t imagine why you need this. Can you elaborate a bit? – MakePeaceGreatAgain Aug 28 '18 at 08:09
  • 3
    Please keep in mind that `new Person()` and `new Person() { Year = 0 }` are completely indistinguishable. *All* fields are initialised in your example. It's just that `Year` is initialised implicitly to its default value. –  Aug 28 '18 at 08:10
  • Check here https://stackoverflow.com/questions/4144778/get-properties-and-values-from-unknown-object – Digital_Jo4 Aug 28 '18 at 08:10
  • Sorry, I mean the fields i am working with inside the method. Like I have 3 fields defined in class, but working just with 2 inside the method. And I would like to count the way i got number: 2 returned – Deryl Aug 28 '18 at 08:11
  • 1
    The problem, as hvd already mentioned, is that there´s no way to distinguish `new Person()` from `new Person { Year = 0 }` because the formers `Year`-property is **implicitely** initialized to zero anyway. – MakePeaceGreatAgain Aug 28 '18 at 08:13
  • Ok, Year was a bad example. I changed Year to Nickname. How can i solve this situation? My use-case: I prepare xls file with columns depend of the documentType. First document type needs name, surname, second document type needs Nickname. When i was using getProperties and iterating through it, some columns were empty, because the property index order went further – Deryl Aug 28 '18 at 08:16
  • Taking the comments in mind, you need to provide a custom initialization to distingish your own default values from the compiler default values for initializing – Greggz Aug 28 '18 at 08:16
  • You could probably use reflection to gather a list of all properties (or fields if you using fields directly, which you are not - you are using properties which are kind of implicitly wrapped fields) and compare them to the default value for the type, or null (if the value is nullable). This seems like an odd thing to do.... Maybe if you explained why you are trying to count fields you have assigned values to, we would be able to help further? – Jay Aug 28 '18 at 08:19
  • @Jay But how do you tell the difference between uninitialized and deliberately set to the default value? Sure, year 0 would be weird, but retryCount 0 might not be so strange. – ProgrammingLlama Aug 28 '18 at 08:22
  • 1
    @John default(T) - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/default-value-expressions is one way that springs to mind - and I understand that it is not foolproof as the OP could initilise the property to the default value, but without knowing *why* the OP is trying to count properties, I don't think anyone here can answer the question correctly. – Jay Aug 28 '18 at 08:24
  • @Jay I have a method for xls file preparation. The column names, depends of some document Type. I pass the data model for a specified document type the way presented in question (with a method). If there are many properties, in right order, I can just iterate through indexes and everything is fine. But if order is not right, like there would be the Name, Nickname, Surname, then I don't know how to iterate it correctly, because if I want to make just name and surname columns, then xls made this way look like: Name | | Surname – Deryl Aug 28 '18 at 08:26
  • @Deryl would it be sufficient for the property setter to record if it had been used? After all, the object initialization pattern is simply syntactic sugar. – ProgrammingLlama Aug 28 '18 at 08:30

1 Answers1

1

If you simply want to know if the properties have been assigned, you could use a pattern like this:

public class Person
{
    private string _name;
    private string _surname;
    private string _nickname;

    public string Name { get => _name; set { _name = value; NameInitialized = true; } }
    public bool NameInitialized { get; private set; }
    public string Surname { get => _surname; set { _surname = value; SurnameInitialized = true; } }
    public bool SurnameInitialized { get; private set; }
    public string Nickname { get => _nickname; set { Nic _nickname = value; NicknameInitialized = true; } }
    public bool NicknameInitialized { get; private set; }

    public Person GetPersonData()
    {
        return new Person()
        {
            Name = "Chris",
            Surname = "Topher"
        };
    }
}

Basically, when you assign a value via the setter, it will set the corresponding boolean property to true. Of course, you could still set Nickname = default(string); and then it would still be counted as "initialized", but I think this solution may solve your problem.

You could also make use of CallerMemberName to get the property name and update a dictionary, for example.

public class Person
{
    private string _name;

    private void SetInitialized([CallerMemberName]string propertyName = "")
    {
        // update a dictionary
    }

    public string Name { get => _name; set { _name = value; SetInitialized(); } }
}

Nullable reference types could also be useful (but that's a feature planned for C# 8).

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86