Can I freely add additional operations in C# public property's getter and setter? To what extent? For example, would the following piece of code be okay (returning and editing a collection which is nested into another collection)?
public ObservableCollection<MyEntity> MyCollection
{
get
{
return myColl.Where(p => p.Name == myName).FirstOrDefault().AnotherCollection;
}
private set
{
myColl.Where(p => p.Name == myName).FirstOrDefault().AnotherCollection = value;
}
}
The only bound is the semantics. You may use whatever operations you find suitable, as long as the general property semantics is preserved. Among others, I would check that
access is reasonably fast
if setter finished w/o error, getter should return the value semantically compatible with the set value
if possible, avoid raising exceptions inside
consecutive gets return semantically equivalent values if internal state didn't change
If you keep the semantics, IMHO any operation is allowed.
Realistically, you are allowed to add most anything you want within a propeties getter and setter. Effectively they are not much more than a easy way to avoid writting this:
private String _value;
public String GetValue
{
return _value;
}
public void SetValue(string value)
{
_value = value;
}
So if you can do it in a method, you can do it in a property (doesn't necessarily mean that you should)
As for what is proper, a lot of that depends on context and many people have differing opinions. The general guidelines I try to follow myself are:
Do not do anything that takes too much time. Properties are expected to be fast.
Do not put anything that will throw an Exception unless it is documented and it makes sense. I will use ArgumentException or NullReferenceException in cases where I have to account for values in the property that will break the code, but otherwise if it needs an exception or I call a method that could result in an exception unrelated to the property itself, then method is better.
Use common sense. If you can say to yourself, I want to get or set a value, then a property makes sense. If I want to do something, then you are probably better off with a method.
This goes back to #1, but if there is no backing field to get or set (automatic properties do this in the background anyways), then you have to think about if a property is really the correct approach.
But as I said, these are my guidelines and I do break them from time to time, but when I do, I tend to make sure it is documented that the property is going to do something unexcepted, or long running.
Your example could throw exceptions if myColl or p are null, so unless you will be 100% certain neither could ever possibly be null, then I would not make this a property.
The code you have provided has a "bad code" smell.
You have used FirstOrDefault functions; which may have null values.
myName variable seems to be a class level variable. Then in a property you seem to be using more than one class level variable (myColl and myName); which seems a bit strange for me.
3.You seem to be returning a deep object, AnotherCollection which is a property of the first item in a list. This may lead to problems; what if;
a. myColl is null,
b. myValue is null,
c. FirstOrDefault returns null,
d. AnotherCollection is null.
I think there are two rules:
Common sense - if you think it shouldn't be like that. Then it probably shouldn't be like that.
Principle of least surprise
it's ok in my opinion,
some will say it's ugly, some will say it's valid or just ok, maybe
nice ...
get/set are in depth 2 methods like get() and set()
what are the 'general' coding guidlines ?
Related
Is it possible to enforce rules or throw an error when using object initializers in C#? I'd like to throw a compiler error or warning if an object is initialized but is missing a certain property.
public class Party
{
public string Name { get; set; }
public string Date { get; set; }
public Location Location { get; set; }
}
public class SignUpForParty
{
public void DoSomething()
{
Party party = new Party()
{
Name = "New Years Party!",
Date = "Dec 31, 1999"
// Show WARNING/ERROR here because no Location given
};
}
}
Essentially, I'm looking for a way to ensure that all objects of type Party are created with valid data for every instance.
Obviously I could do this with overloaded constructors, but in some cases I have a lot of properties and writing constructors to match is messy. I'd like to follow a cleaner C# style.
Obj p = new Obj(1, 2, 3,...n); // too many properties to be pretty
Obviously I could do this with overloaded constructors, but in some cases I have a lot of properties and writing constructors to match is messy. I'd like to follow a cleaner C# style.
Object initializers really shouldn't be considered alternatives to writing a constructor.
You should always include constructors in your types if you have requirements like this. It is a good idea to create a default set of constructors (or use optional arguments on one constructor) which at least provide a guarantee that the object will always be created in a valid, meaningful state.
Object initializers are helpful for optional properties, but shouldn't be relied upon for requirements of your type itself.
You cannot force every property to be initialized with an object initializer.
Even if you could, a consumer of the object could provide default (0, null, ...) values. Depending on your needs, consider validating object state at key times (e.g. before it can be saved to a database).
If you go that route, have a look at the IDataErrorInfo interface.
If your type is not valid when only 2 properties are set then you need to fix your design, not emit an error.
You provide a default constructor, which tells me that I don't have to set anything to use the object after initialization. You provide getters and setters for each property, again, implicitly telling users of your class that it is ok to set on but not the other.
If this is not the case then I suggest you provide a constructor which forces me to supply all three values. Yes, I can still use (null, null, null), but you could check for that and throw an error.
Also, if PropertyA is dependent on PropertyB then either
A) Only one of them should have a setter, or
B) There should be logic in the setter of each to properly initialize the other after the value changes.
This is a design problem, not a language problem. You cannot force the initializer syntax to work differently than how it was spec'd.
Obj p = new Obj(1, 2, 3,...n); // too many properties to be pretty
Code isn't supposed to be 'pretty', it is supposed to work. Even then, a constructor which takes a few arguments is 'ugly'? Huh? Don't buy into the hipster nonsense, write code that works and works well.
The only way I could see this implemented is if there was some event (or equivalent) that was raised when the object initializer was completed. There is currently a Connect request for something to this effect.
Unfortunately, I didn't make the cut for .NET 4.5:
Thank you for your suggestion.
This is a great idea, and has the nice property that it doesn't add to the language surface - it just makes object initializers smarter. In principle that would probably make it a breaking change, but that is something we can look into.
Unfortunately we cannot add any more to the release we are currently building, so I am going to resolve as Won't fix for this release. However, I am capturing the suggestion on our list of features for future discussion.
Thanks again!
Mads Torgersen, C# Language PM
Maybe it'll make it's way into .NET 5+.
What about Code Contracts?. This will assert not only that you assigned a value, but you could also specify valid ranges.
Or for check at runtime with debug builds only, you could use Debug.Assert(...) calls to achieve the same as above.
Is the condition check really redundant in the following sample?:
public class MyClass {
public bool MyProperty { get; set; }
public void DoSomething(bool newValue) {
// R# says: redundant condition check before assignment
// on the following line:
if (MyProperty != newValue) { // <======
MyProperty = newValue;
}
}
}
I know that either way MyProperty will be set to newValue, but is the check redundant?
In Adobe Flex, the getter is called implicitly by the VM its running on whenever a setter is called even though no explicit check is being made. The end result is that checking before an assignment results in two checks, one explicit and one implicit, resulting in a redundant check. Does anything similar happen in C#?
There are only two situations where I've seen this type of check.
The first is when there is an additional line of code which sets another property on the object to True to indicate that the object has been modified. This is typically used when trying to decide whether to persist the state of the object to something like a database.
The second situation is when the types in question are immutable. You might want to avoid setting the value and therefore creating a new string, for example, when the values are the same. Even then, I've only seen it in certain apps where memory usage is critical.
In this specific case, it's logically redundant, since there is no code being executed in the getter - just a straight wrapper around a private field. If you're in the habit of putting stuff in your getter that would have side effects, I'd say to disable that R# warning.
Might be worth trying to put something in the getter of the property, and see if ReSharper still thinks it's redundant. If it does, then I'd call that a R# bug.
I would say that the check is redundant. It would make more sense if you had an implementation of INotifyPropertyChanged, but then the check would be in the setter to avoid triggering the event if no actual change is done.
if (MyProperty != newValue) IS redundant, leaving the line will yield the same result
I'm used to seeing old code like
if (true)
{
...
}
where it's intuitively clear that someone was being either lazy or overly cautious when making a change. I ran across this snippet today, and I'm curious whether there's a functional difference between doing type comparison this way:
private static bool logField(Type t, string fieldname)
{
if (t.ToString() == typeof (Property).ToString())
{
...
}
return true;
}
and doing it this way:
private static bool logField(Type t, string fieldname)
{
if (t == typeof (Property))
{
...
}
return true;
}
I'd say that's generally laziness - but it may not be. For example, you could have two Property types, in the same effective file, but different copies. If typeof(Property) loads it from one file but t is loaded from a different one, your replacement would say they were different but the original code would compare say they were the same.
It's definitely an edge case, and one that you normally want to avoid in the first place... but it's just possible.
I can't think of any good reasons.
In fact, the former will throw if t is null.
The first one compares references of Strings, while the second one actually checks to see if t is of the Property type.
The first one will always be "correct" because the two strings refer to the same object, but the second one is the correct way to check if t is of the Property type.
An equivalent and more readable way to do a type check is
if (t is Property)
No, getting the type object of 2 instances of the same type will always return a reference to the same type object in memory. This means that performing a reference equality check (==) is sufficient.
Essentially, calling:
if (t.ToString() == typeof (Property).ToString())
will call ToString() twice on the same object, where t is the 'Property' type.
I'd say that the first approach was probably done by someone unfamiliar with C#, not necessary being lazy. The string comparison will work for a majority of the time, except:
If t is null it would throw a null reference exception.
It doesn't take namespaces into consideration.
I would recommend the second case, unless you fall into needing the #2 edge case.
If I write:
SomeType simpleName = classWithLongName.otherLongName;
And then use "simpleName" instead of "classWithLongName.otherLongName", will this change the program in any way (for instance performance wise)?
What does the compiler do with this? Does it copy+paste "classWithLongName.otherLongName", everywhere I use "simpleName".
No, the C# compiler doesn't translate a call to "simpleName" to be the same as copying and pasting "classWithLongName.otherLongName". The difference could be profound or simply semantic, but what you're doing is assigning the value from classWithLongName.otherLongName to simpleName. Whether the type is a value type or a reference type will determine exactly what happens and what will happen if you manipulate that value, but you're not creating a function pointer or delegate in doing that.
Whether it will have an effect on performance really isn't something that can be answered here, other than to say that it won't have a NEGATIVE effect. We can't say if it will have a positive effect, since that would depend on what actually happens when you call classWithLongName.otherLongName. If that's an expensive operation, then this could make it faster, but the downside would be that any differences in value upon subsequent calls to classWithLongName.otherLongName wouldn't be reflected if you cached its value in simpleName.
It depends what "otherLongName" is actually doing. If it's a property, then the difference is between executing the property several times or only executing it once. That may or may not change the behaviour of the program in a significant way, depending on what it's doing.
The compiler is only allowed to cache the value and re-use it itself when you always type "classWithLongName.otherLongName" if it knows that the value will not change in the course. However, this is seldom the case.
Therefore, if "classWithLongName.otherLongName" does perform some computation, you'll usually get better performance by caching it manually in a local variable as you suggested. However, keep in mind that you are working with a cached value and that changes in the original value or property will not be reflected on your cached value.
The length of the name however is just metadata and has no influence whatsoever on runtime performance, since the name is already resolved to an internal handle during compilation.
Is this a question about instances or classes?
For instance
namespace MyCompany.MyApp.LongNamespaceName
{
public class MyClassWithALongName {
public SomeType AnInstanceProperty {get;set;}
public static SomeType AStaticProperty {get { ... }}
}
}
Now:
//this gets the static property
SomeType simpleName = MyClassWithALongName.AStaticProperty;
Alternatively:
MyClassWithALongName anInstanceWithALongName = new MyClassWithALongName();
//this gets the instance property
SomeType simpleName = anInstanceWithALongName.AnInstanceProperty;
These will behave in different ways.
There's another case here though, you can create an alias for the actual name of the class:
using simpleName = MyCompany.MyApp.LongNamespaceName.MyClassWithALongName;
...
simpleName anInstance = new simpleName ();
If classWithLongName.otherLongName is a property, than changes to simpleName will NOT change classWithLongName.otherLongName.
If classWithLongName.otherLongName is a public data member (a field) of a value type, than changes to simpleName will NOT change classWithLongName.otherLongName.
If classWithLongName.otherLongName is a public data member (a field) of a reference type, than changes to simpleName WILL change classWithLongName.otherLongName.
Assuming your type is an object (reference) type then simpleName will end up containing a reference to the object returned by classWithLongName.otherLongName. If you are then going to make lots of calls to properties on that object then you may get a performance improvement, especially if otherLongName is a property as opposed to a field.
You can always make it a function.
SomeType simpleName() { return classWithLongName.otherLongName; }
Lets say I have this extention method:
public static bool HasFive<T>(this IEnumerable<T> subjects)
{
if(subjects == null)
throw new ArgumentNullException("subjects");
return subjects.Count() == 5;
}
Do you think this null check and exception throwing is really necessary? I mean, when I use the Count method, an ArgumentNullException will be thrown anyways, right?
I can maybe think of one reason why I should, but would just like to hear others view on this. And yes, my reason for asking is partly laziness (want to write as little as possible), but also because I kind of think a bunch of null checking and exception throwing kind of clutters up the methods which often end up being twice as long as they really needed to be. Someone should know better than to send null into a method :p
Anyways, what do you guys think?
Note: Count() is an extension method and will throw an ArgumentNullException, not a NullReferenceException. See Enumerable.Count<TSource> Method (IEnumerable<TSource>). Try it yourself if you don't believe me =)
Note2: After the answers given here I have been persuaded to start checking more for null values. I am still lazy though, so I have started to use the Enforce class in Lokad Shared Libraries. Can recommend taking a look at it. Instead of my example I can do this instead:
public static bool HasFive<T>(this IEnumerable<T> subjects)
{
Enforce.Argument(() => subjects);
return subjects.Count() == 5;
}
Yes, it will throw an ArgumentNullException. I can think of two reasons for putting the extra checking in:
If you later go back and change the method to do something before calling subjects.Count() and forget to put the check in at that point, you could end up with a side effect before the exception is thrown, which isn't nice.
Currently, the stack trace will show subjects.Count() at the top, and probably with a message with the source parameter name. This could be confusing to the caller of HasFive who can see a subjects parameter name.
EDIT: Just to save me having to write it yet again elsewhere:
The call to subjects.Count() will throw an ArgumentNullException, not a NullReferenceException. Count() is another extension method here, and assuming the implementation in System.Linq.Enumerable is being used, that's documented (correctly) to throw an ArgumentNullException. Try it if you don't believe me.
EDIT: Making this easier...
If you do a lot of checks like this you may want to make it simpler to do so. I like the following extension method:
internal static void ThrowIfNull<T>(this T argument, string name)
where T : class
{
if (argument == null)
{
throw new ArgumentNullException(name);
}
}
The example method in the question can then become:
public static bool HasFive<T>(this IEnumerable<T> subjects)
{
subjects.ThrowIfNull("subjects");
return subjects.Count() == 5;
}
Another alternative would be to write a version which checked the value and returned it like this:
internal static T NullGuard<T>(this T argument, string name)
where T : class
{
if (argument == null)
{
throw new ArgumentNullException(name);
}
return argument;
}
You can then call it fluently:
public static bool HasFive<T>(this IEnumerable<T> subjects)
{
return subjects.NullGuard("subjects").Count() == 5;
}
This is also helpful for copying parameters in constructors etc:
public Person(string name, int age)
{
this.name = name.NullGuard("name");
this.age = age;
}
(You might want an overload without the argument name for places where it's not important.)
I think #Jon Skeet is absolutely spot on, however I'd like to add the following thoughts:-
Providing a meaningful error message is useful for debugging, logging and exception reporting. An exception thrown by the BCL is less likely to describe the specific circumstances of the exception WRT your codebase. Perhaps this is less of an issue with null checks which (most of the time) necessarily can't give you much domain-specific information - 'I was passed a null unexpectedly, no idea why' is pretty much the best you can do most of the time, however sometimes you can provide more information and obviously this is more likely to be relevant when dealing with other exception types.
The null check clearly demonstrates to other developers and you, a form of documentation, if/when you come back to the code a year later, that it's possible someone might pass a null, and it would be problematic if they did so.
Expanding on Jon's excellent point - you might do something before the null gets picked up - I think it is vitally important to engage in defensive programming. Checking for an exception before running other code is a form of defensive programming as you are taking into account things might not work the way you expected (or changes might be made in the future that you didn't expect) and ensuring that no matter what happens (assuming your null check isn't removed) such problems cannot arise.
It's a form of runtime assert that your parameter is not null. You can proceed on the assumption that it isn't.
The above assumption can result in slimmer code, you write the rest of your code knowing the parameter is not null, cutting down on extraneous subsequent null checks.
In my opinion you should check for the null value. Two things that comes to mind.
It makes explicit the possible errors that can happen during runtime.
It also gives you a chance to throw a better exception instead of a generic ArgumentNullException. Thus, making the reason for the exception more explicit.
The exception that you will get thrown will be an Object reference not set to an instance of an object.
Not the most useful of exceptions when tracking down the problem.
The way you have it there will give you much more useful information by specifically stating that it's your subjects reference that is null.
I think it is a good practice to do precondition checks at the top of the function. Maybe it's just my code that is full of bugs, but this practice catched a lot of errors for me.
Also, it's much easier to figure out the source of the problem if you got an ArgumentNullException with the name of the parameter, thrown from the most relevant stack frame. Also, the code in the body of your function can change over time so I wouldn't depend on it catching precondition problems in the future.
It always depends on the context (in my opinion).
For instance, when writing a library (for others to use), it certainly makes sense to fully check each and every parameter and throw the appropriate exceptions.
When writing methods that are used inside a project, I usually skip those checks, attempting to reduce the size of the codebase. But even in this case, there might be a level (between application layers) where you still place such checks. It depends on the context, on the size of the project, on the size of the team working on it...
It certainly doesn't make sense doing it for small projects built by one person :)
It depends on the concrete method. In this case - I think, the exception is not necesary and the better usage will be, if teh extension method can deal with null.
public static bool HasFive<T>(this IEnumerable<T> subjects) {
if ( object.ReferenceEquals( subjects, null ) ) { return false; }
return subjects.Count() == 5;
}
If you call "items.HasFive()" and the "items" is null, then is true that items has not five items.
But if you have extension method:
public static T GetFift<T>(this IEnumerable<T> subjects) {
...
}
The exception for "subjects == null" should be called, because there is no valid way, how to deal with it.
If you look at the source to the Enumerable class (System.Core.dll) where a lot of the default extension methods are defined for IEnumerables classes, you can see that they all check for null references with arguments.
public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, int count)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return SkipIterator<TSource>(source, count);
}
It's a bit of an obvious point, but I tend to follow what I find in the base framework library source as you know that is more than likely to be best practices.
Yes, for two reasons:
Firstly, the other extension methods on IEnumerable do and consumers of your code can expect yours to do so as well, but secondly and more importantly, if you have a long chain of operators in your query then knowing which one threw the exception is useful information.
In my opinion one should check for known conditions that will raise errors later on (at least for public methods). That way it's easier to detect the root of the problem.
I would raise a more informational exception like:
if (subjects == null)
{
throw new ArgumentNullException("subjects ", "subjects is null.");
}