Why? Just why? Why would you put it in a function? Why not implement it? Why not fill the function with Debug.Log and return? It’s beyond me. To me saying “Throw error telling programmer that this empty function hasn’t been implemented.” is like setting up a morning alarm on Sunday at 06:00 AM to remind you, that you are free today and you can continue sleeping.
Why even put that clock there? Its absolutely useless telling me obvious information, why not just turn it off on Saturday?
Why throw NotImplementedException()? Its absolutely useless telling me obvious information, why not just have it return dummy data or implement it in its entirety?
Explain please, what are actual practical uses of NotImplementedException()? Why not just amend them on the spot?
You should always fail early, it’s easier to debug. So instead of swallow error (return dummy data) it’s better to just throw.
Not implemented exceptions have its uses, more so in large agile enterprise teams. You might want to let the testers test part of a feature befor it’s fully complete, etc.
If you can implement it, sure just implement it. However, not all methods are small enough to do so. There are also cases where parts of projects are designed top-down, so you may wanna define all the classes, attributes and methods and then later actually implement them (potentially have multiple people implement different parts). For that, you can (even automatically) add NotImplementedException() to the empty methods. You can also use it for partially implemented methods, for example when there is an else-part missing that is not yet clear how it should be handled, and is currently being discussed in the developer group.
In either of these cases, it wont be possible to miss the missing implementation, which is quite important, especially for larger projects. Otherwise you may run into hard to track bugs and whatnot.
Using Debug.Log() instead has not the same advantage, as it can be easily missed, especially if you make heavy use of Debug.Log() for other things. So yes, there are reasons and use-cases for the NotImplementedException().
Practical example of using NotImplementedException:
You are working on a feature.
In order to implement said feature you need to create a helper method.
For the purposes of your feature, the method only needs to work under certain circumstances. Your main priority at this point isn’t to make this method work in all possible scenarios, your main priority is to get the new feature implemented.
So you write the method so that it works for your feature and throws NotImplementedException under circumstances that you know it doesn’t support yet.
if(!Application.isPlaying)
{
throw new NotImplementedException("Edit mode support not implemented yet.");
}
Some benefits of using NotImplementedException:
Improved readability; you can easily see the circumstances under which the method doesn’t yet work.
It ensures that if somebody was to use the method in circumstances that it didn’t yet support, that it will fail immediately, instead of something random and possibly destructive happening.
It makes it more likely that somebody will implement the missing parts later, since the exception helps make it more clear what aspects are still missing.
With methods that have return values, using Debug.Log and returning something might not be a good option. You are more likely to miss the Debug.Log and there could be bad side effects if you don’t interrupt the execution with an exception.
With exceptions the method invoker has the option to use try-catch. With Debug.Log they are unable to know if something went wrong and will carry on as if nothing unexpected happened.
Using NotImplementedException is a common convention, so when a programmer sees that, they immediately know what has happened. If you use Debug.Log then the error message could take all kinds of different forms. E.g. I once saw someone use “NIY” and did not understand what that was supposed to mean (for them it was obvious that it meant “not implemented yet”).
It might not be the whole thing that’s empty. Maybe it’s only certain branches that aren’t fully implemented.
Another case that’s worth drawing attention to is if you’ve implemented something but not been able to test it - perhaps because it was waiting on other dependencies.
It’s only obvious to people who already know.
Imagine you’re writing some code and just start getting weird behaviour under certain circumstances. You start debugging, and find that the weird behaviour always happens after some method has been called. You look inside that method and only then see some comments saying something is unfinished, and just returns a dummy value. You’ve just had a bunch of your time wasted because of poor communication.
This exception is one possible solution to that. Log messages are indeed another, and in some cases they’ll also get the job done just fine. The difference is that the exception will always draw someone’s attention immediately to the exact right spot, where a log message assumes that either a) everyone always diligently reads the log or b) the resulting error will always be immediately obvious.
I use it in father classes like could be “Base Enemy” where I code common behavior that can be used in all enemies, but at some point it needs to use a function that will be different for all the enemies.
Then i create the empty method in order to avoid the main class to throw a compiling error and later one i implement it in the different children classes. And if forget about it unity throws me the error.
Example:
public class BaseEnemy : MonoBehaviour
{
....
public void NewMovToPlayer()
{
if (IsPlayerOnNavMesh())
{
agent.SetDestination(PlayerManager.Instance.gameObject.transform.position);
}
else
{
StartCoroutine("ExecuteAttack");
}
}
IEnumerator ExecuteAttack()
{
throw new NotImplementedException("Implement on child class");
}
....
}
public class BirdEnemy : BaseEnemy
{
....
IEnumerator ExecuteAttack()
{
StopMoving();
slimeAnimator.SetTrigger("birdSound");
ThrowFeathers();
}
....
}
public class ToxicSlime: BaseEnemy
{
....
IEnumerator ExecuteAttack()
{
StopMoving();
setCurrentState(stateEnum.CHARGING);
slimeAnimator.SetTrigger("charging");
AudioManager.Instance.Play("pre_puke");
yield return new WaitForSeconds(attack_charge_time);
setCurrentState(stateEnum.ATTACKING);
puckParticleSystem.Play();
AudioManager.Instance.Play("slime_puke");
Puke();
}
....
}
In such situations it’s better to use the abstract modifier instead:
public abstract class BaseEnemy : MonoBehaviour
{
public abstract IEnumerator ExecuteAttack();
}
public sealed class BirdEnemy : BaseEnemy
{
public override IEnumerator ExecuteAttack();
{
StopMoving();
slimeAnimator.SetTrigger("birdSound");
ThrowFeathers();
}
}
This makes it a compiler-enforced requirement that all concrete classes that derive from the abstract base class must have an implementation for the abstract method.
Exactly. If the base class requires the child class to implement a certain method, use abstract classes. However in his example a child class could implement a method and throw that exception temporarily or permanetally if for whatever reason it does not apply to this class. Though this is more about interface and communication design and how it’s meant ot be used.
A good example is the IEnumerator interface. It defines a Reset method that by definition should reset the enumerator to start over. That’s the design decision. However almost no enumerator does implement this method, most of the time because certain enumerators can’t really be reset. When you create an IEnumerator / IEnumerable with the yield keyword, the Reset method would throw a NotImplemented because it is not implemented. I have never seen the Reset method being used anywhere. However if someone uses it, he expects it to work as defined, so it should reset / restart the enumeration. However when that’s not possible, you should would be thankful for getting a NotImplemented exception rather than a silent swallow / do nothing behaviour as it would mess up the logic the user expects. The user would “think” he resets the enumeration when it actually didn’t because it’s not possible.
This boils down to what contracts and purpose is behind a certain method. Certain things just must not be used in certain circumstances. Like using DirectoryInfo in a WebGL game or something like that. It’s just an error on the user side to trying to use this method. So it’s an exceptional case that clearly indicates a logic error that should be solved.
As I said, when it comes to your own contracts / interfaces it all depends on the purpose. If you have a generic “Tick” / “Update” method that isn’t specified to do something particular and the actual code in that method only makes sense to the class itself, you most likely would not put a NotImplementedException in there. When you have an interface for items in your inventory and you define a DropToTheGround method, you probably will have certain special objects which should / can be handled like any other item, but can not be dropped. There are many ways how this can be implemented. Implementing a “do nothing” method is bad design. It makes more sense to add a property “CanBeDropped” and the caller should check if the item can be dropped. In that case you would implement a “NIE” in the method because the system should never call the method on objects that can’t be dropped. If you do it anyways, you get an error that clearly shows that you / the user didn’t follow the rules. So it’s a matter of how abstract a certain purpose is and how it’s used.
Of course instead of throwing an exceptuon you could define the drop method to return a boolean or integer to tell you if the item was dropped or how many were dropped. So an item that can not be dropped may just return false / 0. This may make sense depending on the usecase. If you design all the systems yourself, you can easily adjust your contracts between actors to properly communicate. However when you design isolated modules (like default .NET classes) you do want to get a clear error. Imagine you run code that tries to create an AES crypto provider on a platform that doesn’t have any crypto classes implemented. The code simply can not continue without. So having the factory method just returning “null” makes no sense as in the next line you would get a mysterious NullReferenceException which tells you nothing. The NotImplemented exception clearly indicates an oversight of the programmer in regards to the limitations of the platform.
Finally certain things are usually not needed or there was no time to implement them and are therefore not implemented. Like the Process class on IL2CPP . Here they didn’t use a “NIE” which would have been better as it would communicate the fact that it’s not implemented a lot clearer.
You’re right. Forgot that they both exist Though they serve a similar purpose but yes, technically a NotImplementedException would or should be temporary. Though temporary has an unspecified timeframe So it’s like “Yes we should implement that some day but, priorities”.