I am always confused about when to use if (sth == null). Design of delegate in C# is like this:
//Declaration:
private delegate void OnSthHappened();
//In some place, do:
OnSthHappened += SthHappendCallback;
//When use delegate:
if(OnSthHappened != null)
OnSthHappened();
I really think of judging it is null everytime when use OnSthHappened is unnecessary. I know that in compiler, delegate will become a class to handle the callback. Then why the C# compiler doesn't do the other way like:
//Use the delegate directly:
OnSthHappened();
//In the created-by-compiler class, do the judgement:
//object: instance object, Intptr method: a method pointer
if(method != 0x00) //Null, hide the judgement here
{
Invoke(object, method);
}
I just gave a scene of where to judge null, this is giving me hard choices everytime when I try to write API, to do ==null in caller or called functions? Does anyone could give me some style about where to use ==null judgement?
I know that in compiler, delegate will become a class to handle the callback
Delegate (more precise, MulticastDelegate, because in fact we work with multicast delegates) is a class already. The delegate keyword is just a way to declare a MulticastDelegate-derived type.
Where to use if(obj == null) When writing API?
Shortly, check for null:
in public or protected contacts, if the particular method parameter or return value must not be null. If it is null, throw an exception;
in public, protected or private contracts, when value the value could be null, and you can handle that.
public void Method1(Action action)
{
Contact.Requires<ArgumentNullException>(action != null);
}
public object Method2()
{
Contract.Ensures(Contract.Result<object>() != null);
// code here
}
public void Method2(Action action == null)
{
if (action != null)
action();
}
Do not check for null:
in private contacts, when value must not be null.
private void Method3()
{
var result = Method2();
// In case of result == null, NRE is a best option here.
Console.WriteLine(result.ToString().Length);
}
UPD.
why use different strategies between private and public methods? What is the benefit?
Public or protected surface is unpredictable.
You can't guarantee, that user of your class will provide, for example, valid parameter values. That's why you must check them - this is the way to tell the user, that something is wrong in his code. By delivering understandable exception, you can tell, what is wrong exactly. Note, that user hasn't access to your code, and ArgumentNullException on your method call is much more cleaner, that NullReferenceException inside of your method.
On the other hand, your release code should be clean from extra checks.
If you'll return null from any private method, and then try to access a member of that null value, you'll get NRE during debugging or testing. Then you have to fix error in your code and forget it. If you have fixed the error, there's no reason to keep the null-checking alive. This all doesn't avoid Debug.Assert/Contract.Assert or similar. But: a) those thing should live in debug version of your code; b) they must not be after every line of code, because this reduces code readability; c) often it is enough to catch an exception in debugger/unit test result.
Related
I'm using the AddEventHandler method from that answer, but when doing it on an EventHandler with a value type argument that happens:
using System.Reflection;
public class Program
{
public static event EventHandler<bool> MyEvent;
public static void Main()
{
EventInfo eventInfo = typeof(Program).GetEvent(nameof(MyEvent));
AddEventHandler(eventInfo, null, (s, e) => {
if (e == null) return; // either if condition or null conditional operator
Console.WriteLine(e?.ToString());
});
MyEvent(null, true);
}
public static void AddEventHandler(EventInfo eventInfo, object client, EventHandler handler)
{
object eventInfoHandler = eventInfo.EventHandlerType
.GetConstructor(new[] { typeof(object), typeof(IntPtr) })
.Invoke(new[] { handler.Target, handler.Method.MethodHandle.GetFunctionPointer() });
eventInfo.AddEventHandler(client, (Delegate)eventInfoHandler);
}
}
Any explanation?
You are using undocumented, internal api, and what's even worse is that this api accepts raw pointer. So it's not surprising if things go (horribly) wrong if you misuse such api (and you cannot ever be sure you are using it correctly because it's not documented).
Note that AddEventHandler third parameter is EventHandler, which is delegate of this type:
delegate void EventHandler(object sender, EventArgs e);
And your MyEvent delegate type is:
delegate void EventHandler(object sender, int e);
AddEventHandler uses internal undocumented compiler-generated constructor of delegate which accepts two parameters: delegate target and raw pointer to method. It then just passes raw pointer to the method of handler delegate to that constructor without doing any checks. Delegate you pass and delegate being created can be completely incompatible, but you won't notice that until runtime will try to invoke it.
In this case, runtime thinks it has delegate pointing to method void (object, bool), but actually it points to method void (object, EventArgs). You call it via MyEvent(null, true) and runtime passes true boolean value as second argument (it's value type so value is passed directly), but your delegate actually points to method which expects EventArgs, which is a reference type. So it expects an address of some object of type EventArgs. It gets boolean value as if it was pointer to EventArgs.
Now, == null in general case basically just checks if the reference is zero (all bytes are 0). True boolean value is not represented by 0, so null check passes.
Then, it tries to access object located at this "address". It cannot work, you access protected memory and get access violation error. However, as explained in this answer:
but if (A) the access violation happened at an address lower than
0x00010000 and (B) such a violation is found to have happened by code
that was jitted, then it is turned into a NullReferenceException,
otherwise it gets turned into an AccessViolationException
So it is turned into NullReferenceException you observe.
Interesting that if you change your code like this:
MyEvent(null, false);
Then it will run without errors, because false is represented by zero byte, and so e == null check will return true.
You can play with this code a bit more, for example change event type to int:
public static event EventHandler<int> MyEvent;
And then do:
MyEvent(null, 0x00010001);
Now it will throw AccessViolationException instead of NullReferenceException as the linked answer claims (now we are trying to access memory at location higher than 0x00010000 so runtime does not convert this access violation into null reference exception).
Here is another fun thing, we are using code from this answer to obtain memory address of .NET object at runtime, then pass that address into handler:
public static event EventHandler<IntPtr> MyEvent;
public static unsafe void Main() {
// it's not even EventArgs, it's string
var fakeArgument = "Hello world!";
// some black magic to get address
var typedRef = __makeref(fakeArgument);
IntPtr ptr = **(IntPtr**)(&typedRef);
EventInfo eventInfo = typeof(Program).GetEvent(nameof(MyEvent));
AddEventHandler(eventInfo, null, (object s, EventArgs e) => {
if (e == null) return;
// e is actually a string here, not EventArgs...
Console.WriteLine(e?.ToString());
});
MyEvent(null, ptr);
}
This code outputs "Hello world!", for the reasons explained above.
So long story short - don't use such dangerous undocumented internal apis in real code.
I have a C# class which contains the following:
public event Action<int> UnsupportedMessage;
It also has a method containing
if (template != null)
{
...
}
else
{
if (UnsupportedMessage != null)
{
UnsupportedMessage(templateId);
}
}
Another C# class called HealthCheck contains public void MyMessage(int id).
What's supposed to happen is if template is null, an event should call HealthCheck.MyMessage().
So many things are wrong here. UnsupportedMessage is always null so UnsupportedMessage(templateId); never gets executed. Even is I remove if (UnsupportedMessage != null) UnsupportedMessage(templateId); will throw System.NullReferenceException: 'Object reference not set to an instance of an object.'. Even if it did work, there's no reference to HealthCheck.MyMessage() so I don;t know how it could ever be run.
How do I create an event to do what I need?
Update
I tried changing to UnsupportedMessage?.Invoke(templateId); as mentioned in the below answer and added this in the line above it:
UnsupportedMessage += _handlerClass.UnsupportedMessage;
_handlerClass is initialized by the constructor contains this method:
public void UnsupportedMessage(int value)
{
...
}
This initially seemed to work but it seems to be getting called many more times than I expected.
It sounds like you're simply missing the event subscription step; you'd presumably need:
objectThatIsGoingToRaiseTheEvent.UnsupportedMessage += healthCheckInstance.MyMessage;
which will make UnsupportedMessage become non-null, and make everything work. You should also change:
if (UnsupportedMessage != null)
{
UnsupportedMessage(templateId);
}
to either
UnsupportedMessage?.Invoke(templateId);
or (on older C# versions, noting that this is semantically identical)
var handler = UnsupportedMessage;
if (handler != null) { handler(templateId); }
to avoid a race condition that is possible if the last event-handler unsubscribes (-=) between the two reads of UnsupportedMessage in the original version.
I have a method that returns an ItemCollection, I want to stop the function early if there is no information provided. I would normally do this with a return; however as my method expects an ItemCollection it fails. I have this as a work around but it seems frankly hacky. Is there something I am missing. I tried just return; and I would prefer not throw an exception.
private ItemCollection loadLeft_Click(object sender, RoutedEventArgs e)
{
var leftUser = UsrLeft.Text;
if (leftUser == "")
{
MessageBox.Show("No User Entered");
GroupListLeft.Items.Add("");
var fail = GroupListLeft.Items;
return fail;
}
//Succesful test do stuff
var leftItems = GroupListLeft.Items;
return leftItems;
}
You have few options:
throw a new Exception (maybe even a custom one like NoUserEnteredException("someText")).
return null
return an empty collection or dummy object (see Null-object pattern)
The last one is better choice, in this case you don't need write a null-check or a try-catch section in client code.
You will need to return something that equates to an ItemCollection, depending on how you may want the calling procedures to handle such a return you could use a null return:
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return null;
}
Or return a new ItemCollection e.g.
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return new ItemCollection();
}
You will need to return null, like
private ItemCollection loadLeft_Click(object sender, RoutedEventArgs e)
{
var leftUser = UsrLeft.Text;
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return null;
}
//Succesful test do stuff
var leftItems = GroupListLeft.Items;
return leftItems;
}
You can use "return null" which I do from time to time, but its not a good coding convention. Another option is to throw an exception and then catch it. Both is bad coding conventions and makes the code that uses this button add some rather obscure logic and dependencies.
From studying SOLID principles I would argue a better solution is to make a new type of object to return. f.ex. one that holds a list, but also a status message and then make it react a bit like when you have an HTTP request that depends on a success and otherwise cannot expect to have any content. This way, the object makes it clearer what to expect.
A fourth option, since this sounds UI related, is to possible have the click callback somehow and either update the collection, or update with an error message directly. But this might also be a bad coding convention that has impractical dependencies in the code.
Your code seems to return an object when you click on something.
(I am no expert in WPF, i don't know if this is possible).
I would encapsulate the function that returns the ItemCollection in a separate function and check whether the User is valid BEFORE calling this function.
This way you ensure that the ItemCollection is always valid (because you don't even try to retrieve it with an invalid user). Something like this:
private void loadLeft_Click(object sender, RoutedEventArgs e) {
var leftUser = UsrLeft.Text;
if(leftUser != "") {
ItemCollection coll = getItemCollectionForUser(leftUser);
}else {
//Error Handling
}
}
private ItemCollection getItemCollectionForUser(string user) {
//return ItemCollection here
}
Note how I wrote a separate function that returns the ItemCollection and the Click function returns nothing.
I have the following function:
public void Test(string testString)
{
//Do Stuff
}
At some points in my code, I have to repeatedly check if the parameter is empty string/null/whitespace to skip the body method. The usual ways I've done this till now, are the following:
public void Test(string testString)
{
if(!string.IsNullOrWhiteSpace(testString))
{
//Do Stuff only if string has text in it.
}
}
Or
public void Test(string testString)
{
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
Is there a way to create a custom attribute that checks if the parameter of the function is empty etc, to skip the method? I've had some experiece (basic stuff), with custom attributes, but I can't figure out a way to make the attribute skip the method body.
The ideal end product of the implementation would be the following:
[SkipIfEmptyParameter]
public void Test(string testString)
{
//Do Stuff only if string has text in it.
}
Of course, any suggestion is welcome that helps minimize the recurring code if the attribute implementation is not possible.
Edit: Example of the problem I want to solve.
I have the following methods. I get from Microsoft Test Manager, some parameters that our test scenario are expecting (what the values should be). There is a SharedStep implementation that asserts the user's info:
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's name at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserSurname(string surname)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's surname at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserAge(string age)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's age at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserHeight(string height)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's height at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
The "Do Stuff" contain Selenium implementation that handle WebElements and might be time consuming, so if we don't want to validate that specific value, we just skip the whole method.
Now, when creating the scenarios over to Microsoft Test Manager, the shared steps allows the tester to decide what elements of the page will be validated. If some of the parameters are empty, then the code just skips the blocks and goes to w/e validation the user wants (still, the implementation is for every info the user has, but we just assign value to each parameter we want to test, and every parameter that does not have a value, just gets it's method body skipped).
The problem is, if I want to change the condition of skipping the method, I will have to go to each method and manually change the IF statement. Hence why I though it might be a good idea to have an attribute for every method that validates information.
P.S. I'm talking about hundreds of methods that have the IF implementation at the start.
The only way that I know that this can be done using attributes is aspect oriented programming using a product like post sharp and method interception. Alternatively if the methods are defined in an interface this can also be done by using RealProxy but seems more than a little overkill.
The way you are doing it is actually pretty good. But as Evk pointed out in the comments: You should extract the "skip checking" into a separate method, especially if the check is always the same and needs to be changed globally. Using an attribute would solve the problem, but is a little complicated to use.
Instead, take a look at the code below. Looks pretty clear, doesn't it? Don't use too many comments (and don't copy-paste them into every method, that is of no use). This way, you have the same benefits as if you would use a custom attribute but without the ugliness of using reflection.
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
if (ShouldSkipValidation(name)) return;
// code here...
}
private void VerifyUserSurname(string surname)
{
if (ShouldSkipValidation(surname)) return;
// code here...
}
private void VerifyUserAge(string age)
{
if (ShouldSkipValidation(age)) return;
// code here...
}
private void VerifyUserHeight(string height)
{
if (ShouldSkipValidation(height)) return;
// code here...
}
// The MTM scenario does not want to validate values that satisfy the check below
private bool ShouldSkipValidation(string value)
{
return string.IsNullOrWhiteSpace(value) || value == "<>";
}
I don't think attributes make it possible to achieve what you are trying to achieve.
But you can use a custom method invoker instead:
static void Main(string[] args)
{
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), null);
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "");
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "abc");
// RESULT:
// Trying to invoke action...
// Trying to invoke action...
// Trying to invoke action...
// I have been invoked!
}
static void InvokeIfNotNullOrWhitespace(Action<string> action, string inputString)
{
Console.WriteLine("Trying to invoke action...");
if(!string.IsNullOrWhiteSpace(inputString))
action.DynamicInvoke(inputString);
}
static void TestMethod(string input)
{
Console.WriteLine("I have been invoked!");
}
The reason why I think attributes won't work is because they can't control what is going on inside the method. Instead, "other external things" can look at those attributes and decide what to do.
To achieve what you are trying to achieve, an "external thing" would need to look at the attribute and decide if it is executed or not. This would be equivalent to what I wrote: an external invoker that unifies the "check string validity" procedure.
Here are my 4 cents on this,
Calling an attribute involves reflection, already a bad idea as
you need to find out if the attribute is set;
You're avoiding a "1 liner" in your code that actually is quite
easy to type;
Use method overloading;
You can use Aspect oriented programming that will basically inject the below samples in your code at compile time. You can control the way this works with annotations and would not have a negative effect on the generated runtime.
Here are some variations:
//1
if(string.IsNullOrEmpty(testString))
return;
//2
if(string.IsNullOrEmpty(testString) ||string.IsNullOrWhiteSpace(testString) )
return;
When going for 3 just make sure you do not mix returning null, or boolean true/false based on the "missing" text. Only you know how your code should flow.
Perhaps you are looking for method overloading
you can do that by creating 2 methods with the same name in the same class.
You can call the empty MyMethod() from the MyMethod(with string) so you do not duplicate the logic.
return string.IsNullOrEmpty(testString)?MyMethod():MyMethod(testString);
I'm confused about the return value of GetComponent if the requested component is not attached to the object. According to the Unity documentation, GetComponent should return null. However, what appears to be happening is that GetComponent is returning a "null" object of the requested type, rather than the value null.
In this example, my game object does not have a CircleCollider2D attached to it. When I set a breakpoint on the line CircleCollider2D x = GetComponent<CircleCollider2D>();, I get this result
Why is the returned value not null?
EDIT:
Here's a full screenshot of the code and the values in the debugger.
ANOTHER EDIT:
Could it be that Unity has overloaded the == operator so that GetComponent always returns a object, but the object can have an internal "null" state which returns true when compared to null? I can see the following declarations in the UnityEngine namespace
public static bool operator ==(Object x, Object y);
public static bool operator !=(Object x, Object y);
It seems like GetComponent<T>() doesnt return TRUE null. Instead it returns new T with default values that fires MissingComponentException when using any null field. GetInstanceID() and GetHashCode() work because they only use int m_InstanceID which is set to default 0. Not sure how ToString() works but it probably returns "null" when m_InstanceID == 0.
Proof:
void Start()
{
CircleCollider2D getComponent = GetComponent<CircleCollider2D>();
CircleCollider2D empty = null;
CircleCollider2D newCC = new CircleCollider2D();
Debug.LogFormat("getComponent.GetInstanceID() {0}", getComponent.GetInstanceID());
Debug.LogFormat("newCC.GetInstanceID() {0}", newCC.GetInstanceID());
try
{
Debug.LogFormat("empty.GetInstanceID() {0}", empty.GetInstanceID());
}
catch (System.NullReferenceException e)
{
Debug.Log("empty.GetInstanceID() doesnt work, im true null");
}
try
{
string t = getComponent.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("getComponent fires {0} when any field is null",
e.ToString()));
}
try
{
string t = newCC.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("newCC fires {0} when any field is null",
e.ToString()));
}
}
Results:
getComponent.GetInstanceID() 0
newCC.GetInstanceID() 0
empty.GetInstanceID() doesnt work, im true null
getComponent fires UnityEngine.MissingComponentException
newCC fires System.NullReferenceException
Also:
getComponent.GetHashCode() = 0
getComponent.ToString() = "null"
Why getComponent == null is true? Usually it's just:
`getComponent.GetInstanceID() == otherComponent.GetInstanceID()`
In o == null case it's:
return !(
o.GetCachedPtr() != IntPtr.Zero || (!(o is MonoBehaviour) &&
!(o is ScriptableObject) &&
Object.DoesObjectWithInstanceIDExist(o.GetInstanceID())));
So i guess object with InstanceID = 0 never exists.
Search for decompiled UnityEngine/UnityEngine/Object.cs if u want to know more.
Could it be that Unity has overloaded the == operator
Tldr: Yes.
Why is the returned value not null?
According Custom == operator, should we keep it? :
When a MonoBehaviour has fields, in the editor only, we do not set
those fields to “real null”, but to a “fake null” object.
Why? According that article, basically for two reasons:
On Editor mode: get more contextual information on invocations, so if you have an exception you will be able to know which object was the cause.
Every that comes from UnityEngine.Object are wrapped in a C# object to keep the reference to the Unity C/C++ GameEngine Object. In the editor/code we work with the C# elements but those are just a reference to the 'real' c++ objects. Now, the lifetime of those 'real' c++ objects are handled explicitly (if you destroy something the C++ object it will be destroyed and the allocated memory it will be freed) but the C# object will be completely destroyed when the Garbage Collector decides to free that memory. So you will have a not null C# object pointing to a null C++ object. With this fake null trick you will know that this specific C# object is null because in the C++ side it was destroyed.
This is also important when if you have a singleton and if (sm_Instance == null) is not working as expected, you can use: if (EqualityComparer<T>.Default.Equals(sm_Instance, null)) instad.
Edit: Probably this can be caused if your singleton use generics and your type constrain is class
public class Singleton<T> where T : class {
This will cause to use the == operator of a class object, even when your Singleton is a GameEngine Object. One fix for that? Instead of class you can use UnityEngine.Object, like:
public class Singleton<T> where T : UnityEngine.Object {
Related Thread:
https://forum.unity3d.com/threads/null-check-inconsistency-c.220649/#post-1775701
Ps: If you go to UnityEngine.Object assembly, you will be able to see the overload:
Almost at the end...
if you are still looking for solution this worked for me`
var component = parent.GetChild(i).GetComponent<T>();
if(component != null)
{
if (component.ToString().Equals("null") == false)
{
list.Add(component);
}
}
GetComponent is expected to return object of type 'Component. Hence it is not expected to return "null" rather ~null is expected value. Perhaps this strange behavior should be reported to unity3d,