I'm trying to build a class which will initalise its self either by passing in a reference to a record in a database (with the intention that a query will be run against the database and the returned values for the objects properties will be set therein), or by specifying the values "by hand" - this no database call is required.
I've looked at a couple textbooks to discover the "Best-practice" for this functionality and sadly I've come up short.
I've written a couple sample console apps reflecting what I believe to be the two most probable solutions, but I've no Idea which is the best to implement properly?
Sample App #1 uses what most books tell me is the "preferred" way but most examples given alongside those claims do not really fit the context of my situation. I'm worried in here that the flow is not as readable as App #2.
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester() : this(0) { }
public OverloadedClassTester (int _ID) : this (_ID, "", 0)
{
this.age = 14; // Pretend that this was sourced from a database
this.Name = "Steve"; // Pretend that this was sourced from a database
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
This Sample (App #2) "appears" more readable - in that I think it's easier to see the flow of operation. However it does appear efficient in terms of characters saved :p. Also, is it not dangerous that it calls a method of the object before it's fully initialised, or is this not a concern?
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester()
{
initialise(0, "", 21); // use defaults.
}
public OverloadedClassTester (int _ID)
{
var age = 14; // Pretend that this was sourced from a database (from _ID)
var Name = "Steve"; // Pretend that this was sourced from a database (from _ID)
initialise(_ID, Name, age);
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
initialise(_ID, _Name, _age);
}
public void initialise(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
What is the "correct" way to solve this problem, and why?
Thanks,
I would definitely chain the constructors, so that only one of them does the "real work". That means you only have to do the real work in one place, so if that work changes (e.g. you need to call some validation method at the end of the constructor) you only have one place where you need to change the code.
Making "simple" overloads call overloads with more parameters is a pretty common pattern IME. I find it more readable than the second version, because you can easily tell that calling one overload is going to be the same as calling the "bigger" one using the default values. With the second version, you have to compare the bodies of the constructors.
I try not to have more than one constructor which chains directly to the base class wherever possible - unless it's chaining to a different base class constructor, of course (as is typical with exceptions).
Do not use database calls in a constructor. This means your constructor is doing a lot of work. See http://misko.hevery.com/code-reviewers-guide/ (Google guide for writing testable code).
Apart from this, chaining constructors (option 2) looks good. Mostly because as you say it is readable. But why are you assigning this.Name etc in the constructor and doing it again in initialize. You could assign all values in initialize.
Maybe something like this?
public class OverloadedClassTester
{
public int Id { get; private set; }
public string Name { get; private set; }
public int Age { get; private set; }
public OverloadedClassTester (Person person)
: this (person.Id, person.Name, person.Age) { }
public OverloadedClassTester(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
public override string ToString()
{
return String.Format("Id: {0}\nName: {1}\nAge: {2}\n\n",
Id, Name, Age);
}
}
maybe it would be better to use optional parameters? In this case, you would create a single constructor and initialize the values to the parameters you wish to set.
More information: link text
I prefer #1, the chaining constructors, from a maintenance perspective. When someone comes back to edit the code later on, you wouldn't want them to edit the initialise() method and not realize that it is being called from a constructor. I think it is more intuitive to have all the functional parts in a constructor of some kind.
Personally, I use constructor chaining like that all the time.
Related
A user inserts KID NAME, the code instantiate an object and add it to list of objects.
How to give each object a unique number automatically starting at 1, such that first KID(object) gets number 1, second KID gets number 2 etc.
I tried something like this but the result is "stackoverflow".
How would the class should be?
class Kid
{
public string KidName{ get; set; }
private static int Number { get; set; }
public int KidNumber { get; set; }
public Kid (string name)
{
this.KidName = name;
Number++;
this.KidNumber = Number;
}
}
Your code works successfully on my device.
Maybe you have an 'stackoverflow' for other reasons?
If you need only to identify Kid class, the alternative way is to use Guid:
class Kid
{
public string KidName { get; set; }
public Guid KidNumber { get; set; }
public Kid(string name)
{
this.KidName = name;
this.KidNumber = Guid.NewGuid();
}
}
Nothing in your example can induce a StackOverflowException. Stackoverflows occur when you repeatedly call the same method recursively either directly or indirectly (by way of an intermediate) or when you have an instance-level field of the same type as the instance itself (a special case of the former). You don't exhibit either case in your example so it must be due to something else external to the code you've shown. The most your code could potentially exhibit is an OverflowException if you were in a checked context.
That said, your approach is OK at first glance with the obvious pitfall that it is not thread-safe. Two instance could in theory end up with the same KidNumber. You can fix that by making use of the Interlocked class:
using System.Threading;
class Kid
{
private static int _counter;
public string KidName { get; set; }
public int KidNumber { get; set; }
public Kid(string name)
{
this.KidName = name;
this.KidNumber = Interlocked.Increment(ref _counter);
}
}
Like ++ in an unchecked context, this handles the case of overflow; once you hit int.MaxValue, if will automatically wrap to int.MinValue. If you don't want negative IDs you'll have to handle that seperately.
This is probably a very beginner question but I have searched a lot of topics and couldn't really find the same situation, although I'm sure this kind of situation happens all the time.
My project/program is going to track changes to drawings on construction projects and send notifications to people when drawings are changed.
There will be many construction projects (job sites), which will in turn have many drawings in each one. Each drawing will have a couple of revisions (as they get changed, a new revision is created).
Here is my Project Class
public class Project
{
private readonly List<Drawing> _drawings = new List<Drawing>(30);
private readonly List<Person> _autoRecepients = new List<Person>(30);
public int ID { get; private set; }
public string ProjectNumber { get; private set; }
public string Name { get; private set; }
public bool Archived { get; private set; }
public List<Person> AutoRecepients { get { return _autoRecepients; } }
public Project(int id, string projectNumber, string name)
{
if (id < 1) { id = -1; }
ID = id;
ProjectNumber = projectNumber;
Name = name;
}
public bool AddDrawing(Drawing drawing)
{
if (drawing == null) return false;
if (_drawings.Contains(drawing)) { return true; }
_drawings.Add(drawing);
return _drawings.Contains(drawing);
}
public void Archive()
{
Archived = true;
}
public bool DeleteDrawing(Drawing drawing)
{
return _drawings.Remove(drawing);
}
public IEnumerable<Drawing> ListDrawings()
{
return _drawings.AsReadOnly();
}
public override string ToString()
{
return string.Format("{0} {1}", ProjectNumber, Name);
}
}
Here is my Drawing Class
public class Drawing : IDrawing
{
private List<IRevision> _revisions = new List<IRevision>(5);
private List<IssueRecord> _issueRecords = new List<IssueRecord>(30);
private IRevision _currentRevision;
public int ID { get; private set; }
public string Name { get; private set; }
public string Description { get; set; }
public Project Project { get; private set; }
public IRevision CurrentRevision { get { return _currentRevision; } }
public Drawing(int id, string name, string description, Project project)
{
// To be implemented
}
/// <summary>
/// Automatically issue the current revision to all Auto Recepients
/// </summary>
public void AutoIssue(DateTime date)
{
AutoIssue(date, _currentRevision);
}
/// <summary>
/// Automatically issue a particular revision to all Auto Recepients
/// </summary>
public void AutoIssue(DateTime date, IRevision revision)
{
}
public void IssueTo(Person person, DateTime date, IRevision revision)
{
_issueRecords.Add(new IssueRecord(date, this, revision, person));
throw new NotImplementedException();
}
public void IssueTo(Person person, DateTime date)
{
IssueTo(person, date, _currentRevision);
}
public void IssueTo(IEnumerable<Person> people, DateTime date)
{
IssueTo(people, date, _currentRevision);
}
public void IssueTo(IEnumerable<Person> people, DateTime date, IRevision revision)
{
foreach (var person in people)
{
IssueTo(person, date, revision);
}
}
public void Rename(string name)
{
if (string.IsNullOrWhiteSpace(name)) { return; }
Name = name;
}
public void Revise(IRevision revision)
{
if (revision.Name == null ) return;
_revisions.Add(revision);
_currentRevision = revision;
}
public struct IssueRecord
{
public int ID { get; private set; }
public DateTime Date { get; private set; }
public IDrawing Drawing { get; private set; }
public IRevision Revision { get; private set; }
public Person Person { get; private set; }
public IssueRecord(int id, DateTime date, IDrawing drawing, IRevision revision, Person person)
{
if (id < 1) { id = -1; }
ID = id;
Date = date;
Drawing = drawing;
Revision = revision;
Person = person;
}
}
}
And here is the Revision struct
public struct Revision : IRevision
{
public int ID { get; private set; }
public string Name { get; }
public DateTime Date { get; set; }
public IDrawing Drawing { get; }
public IDrawingFile DrawingFile { get; private set; }
public Revision(int id, string name, IDrawing drawing, DateTime date, IDrawingFile drawingFile)
{
if (name == null) { throw new ArgumentNullException("name", "Cannot create a revision with a null name"); }
if (drawing == null) { throw new ArgumentNullException("drawing", "Cannot create a revision with a null drawing"); }
if (id < 1) { id = -1; }
ID = id;
Name = name;
Drawing = drawing;
Date = date;
DrawingFile = drawingFile;
}
public Revision(string name, IDrawing drawing, DateTime date, IDrawingFile drawingFile)
: this(-1, name, drawing, date, drawingFile)
{
}
public Revision(string name, IDrawing drawing)
: this(-1, name, drawing, DateTime.Today, null)
{
}
public void ChangeID(int id)
{
if (id < 1) { id = -1; }
ID = id;
}
public void SetDrawingFile(IDrawingFile drawingFile)
{
DrawingFile = drawingFile;
}
}
My question is to do with the project reference in the drawing class and the drawing reference in the revision struct.
It seems like a bit of a code smell?
It also seems like it may cause issues with serialization in the future.
Is there a better way to do this?
It seems necessary for a drawing object to know what project it belongs to so that if I'm working with individual drawing objects I can know which project they belong to.
Similarly, each revision is essentially "owned" by or part of a drawing. A revision doesn't make sense without a drawing so it needs a reference to the drawing it belongs to?
Any advise would be much appreciated.
What you have are not so much circular references as two examples of
a parent-child relationship which is navigable from both ends.
Yes it is normal and acceptable and no it isn't a code smell. Yes, some serialization tools require you to hint. e.g. Newtonsoft.Json would want the ReferenceLoopHandling.Ignore setting.
Navigability as a concept is not always talked about in OO design, which is unfortunate because it's just the concept you want here. (It is an explicit term in UML).
You often don't need navigability from both ends. Parent-child relationships are often coded from parent to child only. This is really common. For instance, an invoiceline class rarely needs an explicit field for its parent invoice because most applications only ever look at the line after retrieving the parent invoice.
So the design decision is not,
"Does a revison make sense without a drawing?"
But
"Will I ever need to find a drawing given only a revision?"
My guess is that your revisions are like invoice lines, and don't need to navigate to their parent. The answer for the drawings <——> project relation is not obvious to me. (It is an analysis question about your domain, not a question about coding style).
There is a striking difference here between OO code and, for instance, SQL. In a SQL database, it must be the revision table that holds the reference to its parent drawing id. In OO code, the parent class nearly-always holds a reference to the children. The children often don't need a reference to their parent because the only way you access the children is by already having the parent.
Circular references are quite normal in C# programs and data models in general, so don't worry about them. They do have to be specially handled during serialization though.
Yes, it's a circular reference and yes it's a code smell. Furthermore I do think the smell is right in this instance, it is not a good OO design.
Disclaimers
It might be normal for C# programs as #Rugbrød puts it, I can't comment on that, I'm not a C# coder.
This kind of design might be ok for non-oo paradigms, such as "component-based" or procedural programming.
So you can ignore this smell I guess if this is the context of your code.
Details
The main problem is that you are modeling data, not behavior. You want to have the "data" right first, and then you will go on to think about actual functions you want to implement on top of that. Like displaying drawings, archiving, etc. You don't have those yet, but that is in your mind right?
The OO approach (as admittedly not everyone agrees with) is to model behavior. If you want your drawings archived, then implement Drawing.Archive(). And I don't mean setting a flag, I mean really copying it to cold-storage or whatever. The real business-function your application is supposed to do.
If you do that, then you will find, there are no behaviors that mutually need each other, since that is then one behavior obviously. What can happen is, that two behaviors need a third abstract one perhaps (sometimes called Dependency Inversion).
I think the only problem here is Drawing.CurrentRevision
Otherwise, a Revision belongs to a Drawing, which belongs to a Project.
CurrentRevision isn't really a property of the Drawing, it's a shortcut to one item in its 'Revisions' list.
How about changing it to a method GetCurrentRevision() and a CurrentRevisionID property? That way it's obvious that GetCurrentRevision should not be serialised, although the ID is.
We went through structs at class and we've been tasked with creating a method inside the struct that changes the fields of an instance compared with another. For example, changing one's name if the other is a manager.
struct Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get => FirstName + LastName;
}
public int Age { get; set; }
public string Role { get; set; }
public double Salary { get; set; }
public bool IsManager { get; set; }
public static void EditInfo(ref Employee e1, ref Employee e2)
{
if (e1.IsManager)
{
Console.WriteLine($"Feel free to set {e2.FirstName}'s info: ");
e2.FirstName = Console.ReadLine();
e2.LastName = Console.ReadLine();
Console.WriteLine($"From now on thy name is {e2.FullName}!");
}
else if (e2.IsManager)
{
Console.WriteLine($"Feel free to set {e1.FirstName}'s info: ");
e1.FirstName = Console.ReadLine();
e1.LastName = Console.ReadLine();
Console.WriteLine($"From now on thy name is {e1.FullName}!");
}
}
}
Now, I have this gut feeling that my creation is terrible. I'm not sure about how to actually approach this at all, and it looks like a valuable lesson to learn for real business applications. I would appreciate every tip and trick that is necessary to make these methods, that interact with multiple instances of the struct, better.
Edit: Clarification
First you should make the mutable properties private set;, the constructor accept initial state, and make EditInfo an instance method. This more or less treats each Employee like a database record with access control, creating a simpler relationship.
public class Employee
{
public Employee(string firstName, string lastName, bool isManager, ...)
{
FirstName = firstName;
LastName = lastName;
IsManager = isManager;
// remaining properties...
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
public bool IsManager { get; private set; }
// remaining properties...
public void Edit(Employee requester)
{
if (requester.IsManager) {
// query input from the user, make changes, and notify the user.
} else {
// notify the user that he doesn't have permission to edit this employee.
}
}
}
Using it thus becomes:
var manager = new Employee("Your", "Boss", isManager: true);
var sheep = new Employee("John", "Doe", isManager: false);
sheep.Edit(manager); // Essentially says "edit sheep using manager as permission".
Secondly, unless your instructor forbade you from using class, you should make it a class and get rid of all the ref declarations. struct and ref are very useful in the right cirumstances, but unless you're aware of the tradeoffs and code rigorously, its too easy to introduce a bug that will be difficult to reason about considering your experience level.
Classes don't automatically make copies or require the ref keyword. Structs on the other hand do make copies without ref, thus semantically requiring(but not enforcing) it at every call site that makes modifications to it. This has further implications which you may not be aware of. Consider properties. Properties cannot be passed with ref, only locals, fields, and array elements. Unfortunately that means it's currently impossible to pass a struct property by ref(though subject to change in a future C# version). This will likely bite you down the road.
In summary, prefer classes in C# unless you have a good reason to use structs(i.e. GC performance, very special purpose types). Above all, aim for readability.
I'm a very new programmer and understand we want to minimize code redundancy so when we update we can make as few changes as possible and also minimize errors.
So I have a Student class that I want overloaded constructor so If I do back chaining it's like this.
public class Student
{
string name;
int Id;
public Student()
{
}
public Student(string name)
{
this.name = name;
}
public Student(string name, int Id) :this(name)
{
this.Id = Id;
But this is apparently bad because we want all the code in one constructor for what reason? Ease of reading?
public Student() : this(null, 0)
{ }
public Student(string name) : this(name, 0)
{ }
public Student(string name, int Id)
{
this.name = name;
this.Id = Id;
}
If I do this forward chaining then what happens if we add a new field like string major? If I do forward chaining then I create a new overloaded constructor with the added field. But now I have to change all the other constructors to call the new one. If I do backwards chaining I just create a new constructor and call the previous overloaded one.
public Student(string name, int Id, string major):this(name, Id)
{
this.major=major;
}
This seems like it follows OOP better but all examples in my text book show forward chaining and don't say why I shouldn't use back chaining.
If I used named/optional parameters it's even easier.
public Student(string name = null, int Id = 0, string major = null)
{
this.name = name;
this.Id = Id;
this.major = major;
}
And if I need another field I just have to edit the one and only constructor. This seems to follow OOP principles the best or am I mistaken? It at least eliminates code duplication the most. My assignment was to "implement the student class following the principles of OOP". I know all these are valid but is one way the best/accepted way of coding constructors? Are there shortcomings with named/optional params that I'm missing? As a beginner it's very confusing that there's so many ways to code this.
There is no best way, because they are different, each of them has advantages and disadvantages.
Independent constructors and chained constructors are available since C# 1.0, under most circumstances we use chained constructors but sometimes we have to use the former if the two constructors has totally different things to handle.
class Student
{
public Student()
{
DoSomething();
}
public Student(string name)
{
this.Name = name;
DoAnotherThing();
}
}
Comparing with optional parameters constructor, the above two are much longer, but to be honest, they are much safer. Consider the following case:
public class Student
{
public Student(string firstName = null, string lastName = null)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
//it's working fine
//var danny = new Student("danny", "chen");
//as the business grows a lot of students need a middle name
public Student(string firstName = null, string middleName = null, string lastName = null)
{
this.FirstName = firstName;
this.MiddleName = middleName;
this.LastName = lastName;
}
//for a better sequence the programmer adds middleName between the existing two, bang!
Another difference between them is using reflection. Optional parameters will not generate more constructors for you, and the default values will not be applied if you are invoking the constructor using reflection.
I know all these are valid but is one way the best/accepted way of coding constructors?
Not to the best of my knowledge - you have many options. Your colleagues are the best people to talk to to reach a consensus. C# is becoming a very rich language, and that means that there will be many different ways to achieve the same thing.
Are there shortcomings with named/optional params that I'm missing?
Not to the best of my knowledge. Personally I think this is the best solution, but others may differ.
As a beginner it's very confusing that there's so many ways to code this.
Welcome to programming. There's millions of us programmers, and we're all busy adding complexity to the world!
I suggest looking deeper about this assumption :
"But this is apparently bad because we want all the code in one constructor for what reason"
There is Fluent Interface Pattern that puts these things apart, also I can not strongly argue that this directly translates for constructors.
customer
.NameOfCustomer("Shiv")
.Bornon("12/3/1075")
.StaysAt("Mumbai");
Illustrative implementation :
public class Customer
{
public string FullName { get; set; }
public DateTime DateOfBirth { get; set; }
public string Address { get; set; }
public Customer NameOfCustomer(string name)
{
this.FullName = name;
return this;
}
public Customer BornOn(DateTime dateOfBirth)
{
this.DateOfBirth = dateOfBirth;
return this;
}
public Customer StaysAt(string address)
{
this.Address = address;
return this;
}
}
Example source
This is a partial answer. Your "backwards chaining", with one constructor setting some parameter(s) then calling another constructor for the rest, is very reasonable/sensible for normal functions: one function does part of the work, then calls another function for some other work, and so on.
But for public constructors, any one of them can be called by client code, expecting to get a fully constructed object, fully initialized. Some constructors in your example leave members uninitialized (unless what you want is the default value for the type).
As an alternative, you can have private constructors.
When refactoring code, I come up with instances like the following
private string _property = string.Empty;
public string Property
{
set { _property = value ?? string.Empty); }
}
Later on in a method I see the following:
if (_property != null)
{
//...
}
Assuming that _property is only set by the setter of Property, is this code redundant?
I.e is there any way, through reflection wizardry or other methods that _property can ever be null?
Assuming that _property is only set by the setter of Property, is this
code redundant?
Exactly, it is redundant. This is the actual purpose of Properties. We shouldn't access the fields of a class directly. We should access them using a Property. So in the corresponding setter, we can embed any logic and we can rest assure that each time we try to set a value this logic would be verified once more.This argument holds even for the methods of a class. In a method we must use the properties and not the actual fields. Furthermore, when we want to read the value of a field, we should make use of the corresponding getter.
In general, properties enhances the concept of encapsulation, which is one of the pillars of object oriented programming OOP.
Many times there isn't any logic that should be applied when we want to set a value. Take for instance the following example:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
We have declared a class for representing a Customer. A Customer object should have three properties an Id, a FirstName and a LastName.
An immediate question, when someones read this class is why should someone make use of properties here?
The answer is again the same, they provide a mechanism of encapsulation. But let's consider how can this help us in the long run. Let's say that one day someone decides that the first name of a customer should be a string of length less than 20. If the above class had been declared as below:
public class Customer
{
public int Id;
public string FirstName;
public string LastName;
}
then we should check for the length of FirstName in each instance we had created ! Otherwise, if we had picked the declaration with the properties, we could just easily make use of Data Annotations
public class Customer
{
public int Id { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
public string LastName { get; set; }
}
and that's it. Another approach it could be the following:
public class Customer
{
public int Id { get; set; }
private string firstName;
public string FirstName
{
get { return firstName }
set
{
if(value!=null && value.length<20)
{
firstName = value;
}
else
{
throw new ArgumentException("The first name must have at maxium 20 characters", "value");
}
}
}
public string LastName { get; set; }
}
Consider both of the above approaches with having to revisit all your codebase and make this check. It's crystal clear that properties win.
Yes, it is possible through reflection. Nevertheless, I wouldn't worry about reflection -- people using reflection to defeat the design of your class is not something I worry about.
There is, however, something I do worry about: the phrase "Assuming that _property is only set by the setter of Property" is key. You are preventing users of your class from setting property to null.
You do not prevent, however, yourself or some other maintainer of your class from forgetting to only use the property INSIDE your class. In fact, your example has some one checking the field from inside the class rather than the property itself.... which means that, within your class, access comes from both the field and the property.
In most cases (where the problem could only come from inside the class) I would use an assertion and assert the field is not null.
If I really, really, really wanted to make sure that it wasn't null (barring reflection or people hell-bent on breaking things), you could try something like this:
internal class Program
{
static void Main()
{
string example = "Spencer the Cat";
UsesNeverNull neverNullUser = new UsesNeverNull(example);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = null;
Debug.Assert(neverNullUser.TheString != null);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = "Maximus the Bird";
Console.WriteLine(neverNullUser.TheString);
}
}
public class UsesNeverNull
{
public string TheString
{
get { return _stringValue.Value; }
set { _stringValue.Value = value; }
}
public UsesNeverNull(string s)
{
TheString = s;
}
private readonly NeverNull<string> _stringValue = new NeverNull<string>(string.Empty, str => str ?? string.Empty);
}
public class NeverNull<T> where T : class
{
public NeverNull(T initialValue, Func<T, T> nullProtector)
{
if (nullProtector == null)
{
var ex = new ArgumentNullException(nameof(nullProtector));
throw ex;
}
_value = nullProtector(initialValue);
_nullProtector = nullProtector;
}
public T Value
{
get { return _nullProtector(_value); }
set { _value = _nullProtector(value); }
}
private T _value;
private readonly Func<T, T> _nullProtector;
}
It is basically redundant. However, if it were mission critical or if for some reason it caused terrible side effects, it could remain. It is hard to tell, but part of your question was "can reflection change this value to null" to which the answer is yes and can be seen here in this linqpad demo
void Main()
{
var test = new Test();
test.Property = "5";
Console.WriteLine(test.Property);//5
FieldInfo fieldInfo = test.GetType().GetField("_property",BindingFlags.NonPublic | BindingFlags.Instance);
fieldInfo.SetValue(test, null);
Console.WriteLine(test.Property);//null
}
public class Test
{
private string _property = string.Empty;
public string Property
{
get { return _property; }
set { _property = value ?? string.Empty; }
}
}
I know this question is old, but look, I needed that one of my string properties never came up in null.
So I did this, and It worked for me
public string Operation { get; set; } = string.Empty;
In this way the default value is a string empty, but never null.