Setting with constructor is OK, moreover it can make the class immutable (and thus, thread safe):
public class Book {
public Book(string bookName) {
//TODO: Put more validation here if required
BookName = bookName != null
? bookName
: throw new ArgumentNullException(nameof(bookName));
}
// Once set in the constructor, this property won't be changed
public string BookName {get;}
public override string ToString() => BookName;
}
If you let BookName be changed after construction then property with set is quite OK:
public class Book {
// Please, note private - m_BookName field is a hidden implementation detail
private string m_BookName = "???";
public Book() {
}
public string BookName {
get {
return m_BookName;
}
set {
if (null == value)
throw new ArgumentNullException(nameof(value));
//TODO: Put more validation here if required
m_BookName = value;
}
}
public override string ToString() => BookName;
}
What's not OK is to expose a public field:
public class Book {
//TODO: don't put it like this!
public string bookName;
...
}
For instance:
Book myBook = new Book();
...
// bookName field is exposed, anyone can write anything into it
myBook.bookName = null;
...
// Harmless check, isn't it?
if (myBook.bookName.Contains("tale")) { // <- Exception thrown
...
}