I have a public method ChangeLanguage that is in a class library that is supposed to be used by other people who have no idea what the source code is but know what it can do.
public string ChangeLanguage(string language)
{
#if DEBUG
// Check if the new language is not null or an empty string.
language.ThrowArgumentNullExceptionIfNullOrEmpty("language", GetString("0x000000069"));
#else
if (string.IsNullOrEmpty(language))
language = _fallbackLanguage;
#endif
}
For me it looked obvious to check if a language was actually passed to the method and if not, throw an error to the developer. Tho this is a very small performance loss, I think it's better to not throw an exception but just use the fallback language when no language was provided.
I'm wondering if this is a good design approach and if I should keep using it at other places in the library like here:
_appResDicSource = Path.Combine("\\" + _projectName + ";component", _languagesDirectoryName, _fileBaseName + "_" + language + ".xaml");
_clsLibResDicSource = "\\Noru.Base;component\\Languages\\Language_" + language + ".xaml";
ResourceDictionary applicationResourceDictionary;
ResourceDictionary classLibraryResourceDictionary;
try { applicationResourceDictionary = new ResourceDictionary { Source = new Uri(_appResDicSource, UriKind.RelativeOrAbsolute) }; }
catch
{
#if DEBUG
throw new IOException(string.Format(GetString("1x00000006A"), _appResDicSource));
#else
return ChangeLanguage(_fallbackLanguage);
#endif
}
try { classLibraryResourceDictionary = new ResourceDictionary { Source = new Uri(_clsLibResDicSource, UriKind.RelativeOrAbsolute) }; }
catch
{
#if DEBUG
throw new IOException(string.Format(GetString("1x00000006B"), _clsLibResDicSource));
#else
return ChangeLanguage(_fallbackLanguage);
#endif
}
It depends on semantics of the call, but I would consider Debug.Fail (which will be eliminated if DEBUG is not defined):
public string ChangeLanguage(string language)
{
if (string.IsNullOrEmpty(language))
{
Debug.Fail("language is NOK");
language = _fallbackLanguage;
}
}
The issue is that, on the one hand, as mentioned by #OndrejTucny and #poke, it is not desirable to have different logic for different build configurations. It is correct.
But on the other hand, there are cases where you do not want the application to crash in the field due to a minor error. But if you just ignore the error unconditionally, you decrease the chances to detect it even on the local system.
I do not think that there is a universal solution. In general, you may end up deciding to throw or not, to log or not, to add an assertion or not, always or sometimes. And the answers depend on a concrete situation.
No, this is certainly not a good design approach. The problem is your method's DEBUG and RELEASE contracts are different. I wouldn't be happy using such API as a developer.
The inherent problem of your solution is that you will end up with production behavior that cannot be reproduced in the dev/test environment.
Either the semantics of your library is such that either not providing a language code is an error, then always raise an exception, or it is a valid condition that leads to some pre-defined behavior, such as using the 'fallback' language code, then always substitute the default. However, it shouldn't be both and decided only by the selection of a particular compilation of your assembly.
I think this is a bad idea. Mostly because this separates the logic of a debug build and a release build. This means that when you—as a developer—only build debug builds you will not be able to detect errors with the release-only logic, and you would have to test that separately (and in case of errors, you would have a release build, so you couldn’t debug those errors properly). So this adds a huge testing burden which needs to be handled for example by separate unit tests that run on debug and release builds.
That being said, performance is not really an issue. That extra logic only happens in debug builds and debug builds are not optimized for performance anyway. Furthermore, it’s very unlikely that such checks will cause any noticeable performance problems. And unless you profile your application and actually verify that it is causing performance problems, you shouldn’t try to optimize it.
How often is this method getting called? Performance is probably not a concern.
I don't think the decision to select the fallback language is the library's to make. Throw the exception, and let the clients choose to select a default, fallback if desired.
Related
What would be the canonical (if any, otherwise any reliable) way of detecting if the JIT engine is available in a portable way?
For example, Xamarin.iOS does not support JIT since the iOS platform enforces DEP. Mono is quite good at bridging the gap by interpreting most things like lambda expressions these days, but some thing are not (properly) implemented, leading to runtime exceptions that hurt performance badly.
I want to do this detection from a shared Portable Class Library, if possible.
You could try performing an operation that you know will fail on your AoT code but not on JIT (creating a type dynamically, for example) and use a try/catch block to define whether or not JIT is available.
It could be implemented like this (note that this will only fail when the linker is set to "Link All Assemblies"):
private static bool? _isJITAvailable = null;
public static bool IsJITAvailable()
{
if(_isJITAvailable == null)
{
try
{
//This crashes on iPhone
typeof(GenericClass<>).MakeGenericType(typeof(int));
_isJITAvailable = true;
}
catch(Exception)
{
_isJITAvailable = false;
}
}
return _isJITAvailable.Value;
}
I would not do so, though. Do you really need those "better performing callbacks" to begin with? This really sounds like a premature optimization.
After some digging into the Mono source code, it seems the "magic" build-time property is FULL_AOT_RUNTIME. For example, System.Reflection.Emit.AssemblyBuilder is conditionally compiled based on this property being unset, meaning
var canJit = Type.GetType ("System.Reflection.Emit.AssemblyBuilder") != null;
should get me what I want.
Why not test the performance of the two callbacks at runtime?
If yours is slower than the platform's, use the platform's.
If the platform's is slower than yours, use yours.
With the move to EF6.1, our goal is to use exclusivity the Async/Await options speaking with our data sets. While porting from our previous Linq2Sql, there are many .ToList(), .FirstOrDefault(), and .Count()'s. I know we can search and fix those all, but it would be nice if we could, at compile time, prevent those functions from even being permitted into a build. Does anyone have have a creative idea on how to accomplish this? Even if they were compiler warnings that could be thrown (such as use of the Obsolete attribute).
You can use the .NET Compiler Platform to write a Diagnostic and Code Fix that will look for these patterns and provide warnings/errors.
You could even implement a Syntax Transformation to automatically change these constructs - though the effort might be more expensive than just doing it by hand.
Following up to this... i never found a solution that can detect this at compile time, but I was able to do this in code in the DataContext:
public EfMyCustomContext(string connctionString)
: base(string.Format(CONNECTION_STRING, connctionString))
{
#if DEBUG
this.Database.Log = LogDataBaseCall;
#endif
}
#if DEBUG
private void LogDataBaseCall(string s)
{
if (s.Contains("Executing "))
{
if (!s.Contains("asynchronously"))
{
// This code was not executed asynchronously
// Please look at the stack trace, and identify what needs
// to be loaded. Note, an entity.SomeOtherEntityOrCollection can be loaded
// with the eConnect API call entity.SomeOtherEntityOrCollectionLoadAsync() before using the
// object that is going to hit the sub object. This is the most common mistake
// and this breakpoint will help you identify all synchronous code.
// eConnect does not want any synchronous code in the code base.
System.Diagnostics.Debugger.Break();
}
}
}
#endif
Hope this helps someone else, and still would love if there was some option during compile.
I have seen code which includes Contract.Assert like,
Contract.Assert(t != null);
Will using Contract.Assert have a negative impact on my production code?
According to the manual on page 11, they're only included in your assembly when the DEBUG symbol is defined (which, of course, includes Debug builds, but not Release builds (by default)).
In addition to the runtime benefits of Contract.Assert, you can also consider the alternative of using Contract.Assume (Manual section 2.5 page 11) when making calls to legacy code which does not have contracts defined, and if you like having the static warning level cranked up on high (e.g. static checking level more warnings or all warnings - level 3+ - and Show Assumptions turned on).
Contract.Assume gives you the same run time benefits as Contract.Assert, but also suppresses static checks which can't be proven because of the legacy assembly.
e.g. in the below code, with static checking enabled and warnings set to level 3 gives the warning : CodeContracts: requires unproven: someString != null when checking the contracts of MethodDoesNotAllowNull
var aString = Legacy.MethodWithNoContract();
MethodDoesNotAllowNull(aString);
private void MethodDoesNotAllowNull(string someString)
{
Contract.Requires(someString != null);
}
With Legacy Assembly code:
public static string MethodWithNoContract()
{
return "I'm not really null :)";
}
Assume suppresses the warning (but gives the run time Assert benefit in debug builds):
var aString = LegacyAssembly.LegacyMethodWithNoContract();
Contract.Assume(aString != null);
MethodDoesNotAllowNull(aString);
This way, you still get the empirical runtime benefit of the Contract.Assert in debug builds.
As for good practices it is better to have a set of good unit tests. Then code contracts are not that necessary. They may be helpful, but are less important.
Problem Description:
As a single developer I've stumbled across this several times:
Sometimes on a project instead of choosing a cleaner approach it makes sense for efficiency reasons to just add some quick and dirty test-code within production code.
While it may sound like a dirty solution, please keep in mind, that I'm only talking about test-code that should be thrown away anyway, when I just want to quickly check something.
To be 100% sure to not forget to take this code out again I'd like to guard it by a compile time timebomb:
What I mean is some piece of code, preprocessor code or anything basically that allows for compilation for a certain timespan, like half an hour for instance and then automatically results in a compiler error after the time (half an hour) is over. A compiler error would be great because it could directly mark the place of the test-code. (I could have it as the first line(s) within such a throwaway region for instance)
So anything like "throw an error if system time is bigger than this specific DateTime" would be great.
I looked into the preprocessor (not too familiar with it) but the directives #if and #error didn't seem like an option since #if expects a symbol instead of an expression.
Question:
Is such a timebomb possible? Any idea on how to do that?
Or any idea on how to get the efficiency of quick and dirty test-code and be absolutely sure that taking it out again can't be forgotten?
(A run time error would be easy but if a compile time error isn't possible I would need something of a similar quality to it.)
I personally think, that timebombing is the wrong approach. Use build targets to distinguish different purpose of code usage.
// Constructor call will only be allowed for target DEBUG
public class Protect : IDisposable
{
#if DEBUG
[Obsolete("error", false)]
#else
[Obsolete("error", true)]
#endif
public Protect()
{
}
public void Dispose()
{
}
}
Usage
using (new Protect())
{
// do some testcode
// will only compile in DEBUG mode
}
One option is to generate file that has "current time" variable at build time and than simply add check that code should stop working after particular time.
Possible approach to generate file at build time - how to put computed value in RESX at build time C#
This is my first StackOverflow question so be nice! :-)
I recently came across the following example in some C# source code:
public IFoo GetFooInstance()
{
#IF DEBUG
return new TestFoo();
#ELSE
return new Foo();
#ENDIF
}
Which lead me to these questions:
Is the use of "#IF DEBUG" unofficially deprecated? If not what is considered to be a good implementation of its use?
Using a class factory and/or tools like MOQ, RhinoMocks, etc how could the above example be implemented?
Using an IoC container, the entire function becomes redundant, instead of calling GetFooInstance you'd have code similar to:
ObjectFactory.GetInstance<IFoo>();
The setup of your IoC container could be in code or through a configuration file.
Nope. We use it all the time to sprinkle diagnostic information in our assemblies. For example I have the following shortcut used when debugging:
#if DEBUG
if( ??? ) System.Diagnostics.Debugger.Break();
#endif
Where I can change ??? to any relevant expresion like Name == "Popcorn". etc. This ensures that none of the debugging code leaks into the release build.
Just like some of the other posters have mentioned, I use #if statements all the time for debugging scenarios.
The style of code that you have posted is more of a factory creation pattern, which is common. I use it frequently, and not only do I not consider it depreciated, I consider the use of #if and #define statements to be an important tool in my bag of tricks.
I believe CastleWindsor (http://www.castleproject.org/container/index.html) also has an IoC container. I believe the general pattern is that in the configuration file, you state that TestFoo or IFoo will be the class created when CastleWindsor initializes the IoC container.
Yes. I would strongly advise AGAINST using "#IF DEBUG" except in rare circumstances
It was common place in C, but you should not use in a modern language such as C# for several reasons:
Code (and header) files become nightmarish
It is too easy to make a mistake and leave in/out a conditional for a Release build
Testing becomes a nightmare: need to test many combinations of builds
Not all code is compile checked, unless you compile for ALL possible
conditional symbols!
#Richard's answer shows how you can replace using IoC (much cleaner).
I strongly deprecate #if; instead use if with a manifest constant:
#define DEBUG 0 // actually in a header or on a command line
public IFoo GetFooInstance()
{
if (DEBUG)
return new TestFoo();
else
return new Foo();
}
Why is #IF bad? Because in the #IF version, not all code is typechecked. For complicated, long-lived codes, bitrot can set in, and then suddenly you need DEBUG but the code won't build. With the if version, the code always builds, and given even the most minimal optimization settings, your compiler will completely eliminate the unreachable code. In other words, as long as DEBUG is known to be always 0 (and #define will do that for you), there is no run-time cost to using if.
And you are guaranteed that if you change DEBUG from 0 to 1, the system will build.
Your compiler should be smart enough to figure out that:
final DEBUG=false;
...
if(DEBUG)
return new debugMeh();
else
return new meh();
the method never has to be called and can, in fact, be compiled out of the final assembly.
That plus the fact that even the unoptimized performance difference wouldn't amount to anything significant makes using some different syntax mostly unnecessary.
EDIT: I'd like to point out something interesting here. Someone in comments just said that this:
#IF DEBUG
return new TestFoo();
#ELSE
return new Foo();
#ENDIF
was easier to write than this:
if(DEBUG)
return new TestFoo();
else
return new Foo();
I find it really amazing the lengths that people will go to to defend the way they've done things as correct. Another said that they would have to define a DEBUG variable in each file. I'm not sure about C#, but in Java we generally put a
public static final DEBUG=true;
in our logger or another central factory object (although we actually find better ways to do this--such as using DI).
I'm not saying the same facilities don't exist in C#, I'm just amazed at the lengths people will go to to prove the solution they hold onto because of habit is correct.