C
C#3mo ago
Jiry_XD

How to prevent nulls using this approach for Object Initializers?

In C# I have this class:
using System.Diagnostics.CodeAnalysis;
using System.Net.Mail;

namespace Domain.Customers;

public class EmailAddress
{
private MailAddress email;

public EmailAddress()
{
// Default constructor so I can use object initializer.
}

[SetsRequiredMembers]
public EmailAddress(string email)
{
Email = email;
}
public required string Email
{
get => email.ToString();
set => email = new MailAddress(value);
}

}
using System.Diagnostics.CodeAnalysis;
using System.Net.Mail;

namespace Domain.Customers;

public class EmailAddress
{
private MailAddress email;

public EmailAddress()
{
// Default constructor so I can use object initializer.
}

[SetsRequiredMembers]
public EmailAddress(string email)
{
Email = email;
}
public required string Email
{
get => email.ToString();
set => email = new MailAddress(value);
}

}
As you can see I have two constructors, when using object initializers I need to use one of them. I like using object initializers using no constructor aka the default constructor but because I added it there is no default so I added it. But now the problem is that people can call new EmailAddress() without passing an email and it can stay null that way? How can I still be able to have an empty constructor so I can use object initializers without having the risk somoene calls new EmailAdress();?
12 Replies
Angius
Angius3mo ago
The property is required, so it should enforce it being set during initialization
MODiX
MODiX3mo ago
Angius
REPL Result: Failure
public class EmailAddress
{
private MailAddress email;

public EmailAddress()
{
// Default constructor so I can use object initializer.
}

[SetsRequiredMembers]
public EmailAddress(string email)
{
Email = email;
}
public required string Email
{
get => email.ToString();
set => email = new MailAddress(value);
}
}

var e = new EmailAddress();
public class EmailAddress
{
private MailAddress email;

public EmailAddress()
{
// Default constructor so I can use object initializer.
}

[SetsRequiredMembers]
public EmailAddress(string email)
{
Email = email;
}
public required string Email
{
get => email.ToString();
set => email = new MailAddress(value);
}
}

var e = new EmailAddress();
Exception: CompilationErrorException
- Required member 'EmailAddress.Email' must be set in the object initializer or attribute constructor.
- The type or namespace name 'MailAddress' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'SetsRequiredMembersAttribute' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'SetsRequiredMembers' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'MailAddress' could not be found (are you missing a using directive or an assembly reference?)
- Required member 'EmailAddress.Email' must be set in the object initializer or attribute constructor.
- The type or namespace name 'MailAddress' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'SetsRequiredMembersAttribute' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'SetsRequiredMembers' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'MailAddress' could not be found (are you missing a using directive or an assembly reference?)
Compile: 459.912ms | Execution: 0.000ms | React with ❌ to remove this embed.
Angius
Angius3mo ago
As you can see, a compile error
Jiry_XD
Jiry_XDOP3mo ago
Oh so they can't call the empty constructor witouth a initializer that sets the email? Thanks 🙂 Coming from java its a bit getting used to the initializers and auto setters and getters but I am getting the hang of it 😛 Another related question, in EF Core I can do:
[EmailAddress]
[NotMapped]
public EmailAddress? EmailAddress { get; set; }
[EmailAddress]
[NotMapped]
public EmailAddress? EmailAddress { get; set; }
This is in Customer.cs entity. I guess EmailAddress is then not getting stored to the db because it is not mapped. I don't need it mapped I just need to store it as a string. What would be a clean way to do this?
Angius
Angius3mo ago
EF entities should only contain what the table is supposed to contain
Jiry_XD
Jiry_XDOP3mo ago
Right, so I want to get the value out of EmailAddress string and store that. (I read about primitive obsession, ... that is why I am trying it this way)
Angius
Angius3mo ago
Use a converter, or something like Vogen that comes with such converters
Jiry_XD
Jiry_XDOP3mo ago
Hmm I'll look into that, thanks
333fred
333fred3mo ago
Is there a particular reason you're including both of those constructors? It seems a bit weird
Jiry_XD
Jiry_XDOP3mo ago
This worked great. I used implicit operators and ef conversion 😁 Some code used a constructor but I made a new class and only wanted to change the class name by the code. Therefore I added the name constructor. To still be able to use object initializers I added the second empty constructor.
333fred
333fred3mo ago
That doesn't seem like a great reason. I'd do just one or the other
Jiry_XD
Jiry_XDOP3mo ago
True, laziness is the better reason there I didn't want to alter the code 😅 Anyways may I thank you both for your feedback and help I really appreciate it 🙂
Want results from more Discord servers?
Add your server