Search code examples
c#objectinheritanceinterfaceabstract-class

How to force to implement all fields a C# object?


I have this object on a class library (project "A" that I want to use in my multiple projects ("B" and "C"):

public class Notification : INotification
{
    public string Id { get; set; }

    public int Type { get; set; }

    public IList<Message> Messages { get; set; }
}
public class Message: IMessage
{
    public string Key { get; set; }

    public string Value { get; set; }

    public string Culture { get; set; }
}
public interface INotification
{
    string Id { get; set; }

    int Type { get; set; }

    IList<Message> Messages { get; set; }
}

Now If I want to create this object on my project "B" I need to do the flowing:

static void Main()
{
    Notification notification = new Notification()
    {
        Id = "someId",
        Type = 1,
        Messages = new List<Message>()
        {
            new Message()
            {
                Culture = "en-US",
                Key = "Some key",
                Value = "Some value"
            }
        }
    };

    Console.WriteLine(notification.Id);
}

The problem is, since all fields are need to be Required if I don't initialize for example the "Type" no error is shown. What I want is that my project "B" implement the "Notification" object like I want, with all required fields, so my message can not be created without the "Type". How can I do this? Do I need to create an abstraction?


Solution

  • In c#, the way to require field initialization is to provide them as constructor arguments.

    public class Notification : INotification
    {
        public Notification(string id, int type, IList<Message> messages)
        {
            this.Id = id;
            this.Type = type;
            this.Messages = messages;
        }
    
        public string Id { get; set; }
    
        public int Type { get; set; }
    
        public IList<Message> Messages { get; set; }
    }
    

    Without a default constructor, it is now impossible to construct a Notification without specifying a Type. This is enforced at compile-time, not run-time.

    If you want null checks, you will have to add them yourself as part of the constructor logic. You can also add a range check for the int or other validation.

    Note: Type is a terrible name for a variable.