I have the following code, the idea is simple if the object is in cache get it, if not then retrieve it from the data source and save it into cache, I am using resharper and I got this warning but cant understand why
public static ModulosPorUsuario GetModulesForUser(string identityname)
{
// It needs to be cached for every user because every user can have different modules enabled.
var cachekeyname = "ApplicationModulesPerUser|" + identityname;
var cache = CacheConnectionHelper.Connection.GetDatabase();
ModulosPorUsuario modulosUsuario;
//get object from cache
string modulosUsuariosString = cache.StringGet(cachekeyname);
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
if (modulosUsuariosString != null)
{
//conver string to our object
modulosUsuario = JsonConvert.DeserializeObject<ModulosPorUsuario>(modulosUsuariosString);
return modulosUsuario;
}
// ReSharper disable once HeuristicUnreachableCode
modulosUsuario = DbApp.ModulosPorUsuario.Where(p => p.Email == identityname).FirstOrDefault();
//convert object to json string
modulosUsuariosString = JsonConvert.SerializeObject(modulosUsuario);
//save string in cache
cache.StringSet(cachekeyname, modulosUsuariosString, TimeSpan.FromMinutes(SettingsHelper.CacheModuleNames));
return modulosUsuario;
}
There's quite a lot going on here, but the bottom line, this is a ReSharper bug - the value can certainly be null, and I have a much smaller example proving it.
First, let's figure out what's going on in your code. I had to dig a little bit into the StackExchange.Redis library that you're using. Your cache object is, in fact, an IDatabase, which is implemented by the RedisDatabase class. The StringGet method that you're using returns a RedisValue, which is a struct. This, by itself, would make perfect sense why ReSharper tells you it can never be null - value types can't!
However, you're putting the result into a string variable! This works because the RedisValue struct defines a bunch of implicit operators to convert the value into the requested type. In case of a string, notice that if the blob is empty, an empty string is returned:
RedisValue.cs
/// <summary>
/// Converts the value to a String
/// </summary>
public static implicit operator string(RedisValue value)
{
var valueBlob = value.valueBlob;
if (valueBlob == IntegerSentinel)
return Format.ToString(value.valueInt64);
if (valueBlob == null) return null;
if (valueBlob.Length == 0) return "";
try
{
return Encoding.UTF8.GetString(valueBlob);
}
catch
{
return BitConverter.ToString(valueBlob);
}
}
But from this code it's obvious that the string can be null as well.
This makes ReSharper incorrect to flag that line, and it can be reproduced with a smaller example:
static void Main(string[] args)
{
string value = MyStruct.GetValue();
if (value == null) // <- ReSharper complains here, but the value is null!
{
return;
}
}
public struct MyStruct
{
public static MyStruct GetValue() => new MyStruct();
public static implicit operator string(MyStruct s)
{
return null;
}
}
I reported this issue to JetBrains, they will fix it.
In the meantime, you might want to keep that comment, disabling ReSharper warning.
Related
In code which regularly needs debug logging, I end up with large blocks of code such as:
int someVar = 1;
bool anotherVar = true;
//...
string lastVar = "foo";
// littered through the code
Log._Debug(
"arbitrary message string",
$"{nameof(someVar)} = {someVar} " +
$"{nameof(anotherVar)} = {anotherVar} " +
// ...
$"{nameof(lastVar)} = {lastVar} "
);
These debug blocks can sometimes be huge (20+ vars being logged) and they can occur dozens of times in a class making the whole thing completely unreadable. Sadly they're necessary - sometimes we need to send debug builds to users (they can't run debugger, it's easier just to get them to run the debug build and send us the logs). It's also old code base which is why it's such a freaking mess.
I'm trying to find a way to debloat the debug chunks in the code, just to make it less depressing to maintain lol.
In my quest to find cleaner syntax, I found https://stackoverflow.com/a/9801735 which shows how to get member name from a lambda function. Which made me wonder, is it possible to create something a bit like this...?
Log._Dump(
"arbitrary message string",
() => somevar,
() => anotherVar,
// ...
() => lastVar
);
So I tried creating a method using params as follows:
[Conditional("DEBUG")]
public static void _Dump(string message, params Func[] vars) {
// ^ what <T> do I use?
}
private static string GetMemberName<T>(Expression<Func<T>> memberExpression) {
// this would eventually return $"{memberName} = {memberValue}"
// which, btw, I have no idea if that's even possible yet
// but I didn't get that far as still trying to work out how to do
// the _Dump() method params above :/
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
I don't know how to do params array of functions with varying return types.
I could potentially just make the params a string array and do the GetMemberName manually for each lambda, for example:
private string NV<T>(Expression<Func<T>> memberExpression) {
// ...code...
return $"{memberName} = {memberValue}";
}
Log._Dump(
"arbitrary message string",
NV(() => somevar),
NV(() => anotherVar),
// ...
NV(() => lastVar)
);
But that's adding boilerplate to the code again which is what I'm trying to avoid. Is there any way I can get it working without that extra NV() wrapper?
EDIT: It's really old codebase and we're stuck with .Net Framework 3.5 so limited to C# 6 or something like that.
C# 10 introduced [CallerArgumentExpression] (docs), a way to pass a string representation of the callers source code. So you could write a helper method;
public void Log<T>(T value, [CallerArgumentExpression("value")] string name=null)
=> Log($"{name} = {value}");
But you could also combine this with another new feature, [InterpolatedStringHandler] (docs) to log the name of any variable inside an interpolated string.
[InterpolatedStringHandler]
public ref struct DebugLogHandler
{
private readonly StringBuilder sb;
public DebugLogHandler(int literalLen, int formattedCount)
{
sb = new StringBuilder(literalLen);
}
public void AppendLiteral(string s) => sb.Append(s);
public void AppendFormatted<T>(T value, [CallerArgumentExpression("value")] string name=null)
{
sb.Append(name);
sb.Append("=");
sb.Append(value?.ToString());
}
public string BuildMessage() => sb.ToString();
}
public static void Log(string message) { ...TODO... }
public static void Log(DebugLogHandler builder)
=> Log(builder.BuildMessage());
var variableName = "value";
Log($"Something {variableName}");
In debugging step through, Visual Studio 2013 shows BitConverter.IsLittleEndian is:
false: When I hover mouse on BitConverter and see the value of BitConverter.IsLittleEndian and
true: When I put it in a variable like var x = BitConverter.IsLittleEndian;
I assume BitConverter.IsLittleEndian should be already evaluated because I have called GetBytes on BitConverter so it's static constructor should be called at this point, right? What am I missing?
My code is this (I wanted to generate sequential Guid; rest is bytes of a long counter - at this version):
static Guid Id(long ticks, byte[] rest)
{
var ticksBytes = BitConverter.GetBytes(ticks).PolishEndian();
// var x = BitConverter.IsLittleEndian; // <- TESTED HERE
int a = BitConverter.ToInt32(new byte[] { ticksBytes[4], ticksBytes[5], ticksBytes[6], ticksBytes[7] }.PolishEndian(), 0);
short b = BitConverter.ToInt16(new byte[] { ticksBytes[2], ticksBytes[3] }.PolishEndian(), 0);
short c = BitConverter.ToInt16(new byte[] { ticksBytes[0], ticksBytes[1] }.PolishEndian(), 0);
return new Guid(a, b, c, rest.PolishEndian(true).ToArray());
}
static byte[] PolishEndian(this byte[] ba, bool reverse = false)
{
var flag = reverse ? BitConverter.IsLittleEndian : !BitConverter.IsLittleEndian;
if (flag) return ba.Reverse().ToArray();
return ba;
}
Note that in this case IsLittleEndian is actually a field and not a property. That has an effect on how the EE is able to process the value.
I tried this out locally and this is the behavior I saw
First i stepped until the cursor hit the var ticksBytes line. At that point I observed that IsLittleEndian == false. This is actually expected at this point. The EE does not always need to force a static constructor to run in order to read fields. Hence it is just reading the value as is and because no other code for BitConverter has run the value is false
Immediately after stepping over that line I observe that IsLittleEndian == true. The CLR ran the static constructor in order to execute the GetBytes method and hence that set the field. The EE was then reading the set field.
Note that you can recreate this example with your own code. For example
static class Test {
static readonly bool example;
static Test() {
example = true;
}
internal static void Go() {
// example == true
}
}
class Program {
static void Main() {
// Test.example == false;
Test.Go();
}
}
Earlier I mentioned that the EE didn't always need to execute a static constructor in order to read fields. One case where it often needs to is when reading static fields off of a generic type. The storage for a static field of a generic type isn't created essentially until the CLR instantiates an instance of the type. Hence in order to read a field off of a generic type which hasn't yet been used the EE will create an instance under the cover in order to force the CLR to read it. For example
static class Test<T>
{
static readonly bool example = false;
static Test()
{
example = true;
}
}
If you add this to your program and then evaluate the following in the watch window
Test<int>.example
you will find that the value is true clearly indicating the cctor ran
How do I know the log the last property that is null?
For example,
var a = "somevalue";
......
......
if(a == null)
{
Log.Error(MethodBase.GetCurrentMethod().Name + "Property : a is null");
//blah blah
}
Like how I use the reflection to get the current method name, there should be some means by which I can log the latest local variables (or a property or fields)
that is being compared ? I use, log4net by the way to log the errors.
1) Is there any method to achieve this or should we manually log it?
2) Is there any custom method that prints the class -> MethodName -> Propertyname(or FieldName) that is null?
Thanks for your time in advance.
As mentioned by #fsimonazzi, "a" would be a local variable.
That being said there is still no way to examine the current compare operation as in MSIL there is no formal concept of an IF block - only conditional jumps.
If you wanted to get really crazy with the reflection, you may be able to find the current executing instruction and look around near that for a variable, but even then, you will not find the name - only a reference - as names are only used prior to compilation.
Either way, reflection is not going to help you here.
Instead, try using Exceptions - specifically ArgumentNullException. This body of code would become:
void doStuff(string param1, int param2)
{
if (param == null)
throw new ArgumentNullException("param1", "param1 must not be null");
if (param2 < 0)
throw new ArgumentOutOfRangeException("param2", "param2 should be non-negative.");
//method body
}
then, when you call the method, you can catch the exception and log it - no matter what it may be.
public static void Main(string[] args)
{
try
{
doStuff(null, 3);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Tools like FxCop can help make sure that you are properly validating each parameter.
Properties are actually implemented as methods, so reflection could help you there. If, for example, you were validating in a property and wanted to log the position automatically, you could.
private object _cachedObject = null;
public object CachedObject
{
get
{
if (_cachedObject == null)
{
log(MethodBase.GetCurrentMethod().Name, "creating cached object");
_cachedObject = createCachedObject();
}
return _cachedObject;
}
}
The .Net Framework 4.5 also brings with it a new attribute that can be used to replace the MethodBase.GetCurrentMethod().Name construct you are using to get the method name. See [CallerMemberNameAttribute][3].
I've been trying to figure out how I could use the Maybe monad in iSynaptic.Commons in a context where my value retriever could throw an exception:
For example:
dynamic expando = new Expando();
expando.Name = "John Doe";
var maybe = Maybe.Defer(()=>(string)expando.NonExistingProperty);
//In this context I would like the exception which is thrown
//to result in Maybe<string>.NoValue;
if(maybe.HasValue) {
//Do something
}
Is this possible with the implementation of maybe that is out there
There are several ways of using iSynaptic.Commons to allow an exception. Each way I found requires the .Catch() extension method to let the monad know to silently catch the exception. Also, be careful when accessing the property maybe.Value. If this property is Maybe.NoValue, an InvalidOperationException will be thrown.
1) Create a "OnExceptionNoValue" extension method. This will check the Maybe to see if it has an exception. If it does, a NoValue Maybe will be returned. Otherwise the original Maybe will be returned.
public static class MaybeLocalExtensions
{
public static Maybe<T> OnExceptionNoValue<T>(this Maybe<T> maybe)
{
return maybe.Exception != null ? Maybe<T>.NoValue : maybe;
}
}
// Sample Use Case:
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch()
.OnExceptionNoValue();
2) Create a "BindCatch" extension method. This changes the behavior of the normal bind when an exception is present to return Maybe.NoValue instead of throwing an exception.
public static class MaybeLocalExtensions
{
public static Maybe<TResult> BindCatch<T, TResult>(this Maybe<T> #this, Func<T, Maybe<TResult>> selector)
{
var self = #this;
return new Maybe<TResult>(() => {
if (self.Exception != null)
return Maybe<TResult>.NoValue;
return self.HasValue ? selector(self.Value) : Maybe<TResult>.NoValue;
});
}
}
// Sample Use Case:
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch()
.BindCatch(m => m.ToMaybe());
3) This way also uses the Catch() extension method, but uses the maybe.HasValue property instead of relying on extension methods. If an exception is present in the Maybe, the HasValue property is false. When this value is false, the Maybe.NoValue can replace the value of the variable maybe or whatever needs to be done in this case.
dynamic expando = new ExpandoObject();
expando.Name = "John Doe";
// This example falls to the else block.
var maybe = Maybe.Defer(() => (string)expando.NonExistingProperty).Catch();
//In this context I would like the exception which is thrown
//to result in Maybe<string>.NoValue;
if (maybe.HasValue) {
//Do something
Console.WriteLine(maybe.Value);
} else {
maybe = Maybe<string>.NoValue; // This line is run
}
// This example uses the if block.
maybe = Maybe.Defer(() => (string)expando.Name).Catch();
//to result in Maybe<string>.NoValue;
if (maybe.HasValue) {
//Do something
Console.WriteLine(maybe.Value); //This line is run
} else {
maybe = Maybe<string>.NoValue;
}
These answers are all variations on the same theme, but I hope they are helpful.
Recently I've found myself writing methods which call other methods in succession and setting some value based on whichever method returns an appropriate value first. What I've been doing is setting the value with one method, then checking the value and if it's not good then I check the next one. Here's a recent example:
private void InitContent()
{
if (!String.IsNullOrEmpty(Request.QueryString["id"]))
{
Content = GetContent(Convert.ToInt64(Request.QueryString["id"]));
ContentMode = ContentFrom.Query;
}
if (Content == null && DefaultId != null)
{
Content = GetContent(DefaultId);
ContentMode = ContentFrom.Default;
}
if (Content == null) ContentMode = ContentFrom.None;
}
Here the GetContent method should be returning null if the id isn't in the database. This is a short example, but you can imagine how this might get clunky if there were more options. Is there a better way to do this?
The null coalescing operator might have the semantics you want.
q = W() ?? X() ?? Y() ?? Z();
That's essentially the same as:
if ((temp = W()) == null && (temp = X()) == null && (temp == Y()) == null)
temp = Z();
q = temp;
That is, q is the first non-null of W(), X(), Y(), or if all of them are null, then Z().
You can chain as many as you like.
The exact semantics are not quite like I sketched out; the type conversion rules are tricky. See the spec if you need the exact details.
You could also do something a little more sneaky, along the lines of this:
private Int64? GetContentIdOrNull(string id)
{
return string.IsNullOrEmpty(id) ? null : (Int64?)Convert.ToInt64(id);
}
private Int64? GetContentIdOrNull(DefaultIdType id)
{
return id;
}
private void InitContent()
{
// Attempt to get content from multiple sources in order of preference
var contentSources = new Dictionary<ContentFrom, Func<Int64?>> {
{ ContentFrom.Query, () => GetContentIdOrNull(Request.QueryString["id"]) },
{ ContentFrom.Default, () => GetContentIdOrNull(DefaultId) }
};
foreach (var source in contentSources) {
var id = source.Value();
if (!id.HasValue) {
continue;
}
Content = GetContent(id.Value);
ContentMode = source.Key;
if (Content != null) {
return;
}
}
// Default
ContentMode = ContentFrom.None;
}
That would help if you had many more sources, at the cost of increased complexity.
Personally, I find when I have lots of statements that are seemingly disparate, it's time to make some functions.
private ContentMode GetContentMode(){
}
private Content GetContent(int id){
}
private Content GetContent(HttpRequest request){
return GetContent(Convert.ToInt64(request.QueryString["id"]));
}
private void InitContent(){
ContentMode mode = GetContentMode();
Content = null;
switch(mode){
case ContentMode.Query:
GetContent(Request);
break;
case ContentMode.Default:
GetContent(DefaultId);
break;
case ContentMode.None:
... handle none case...
break;
}
}
This way, you separate your intentions - first step, determine the content mode. Then, get the content.
I suggest you try some kind of Factory design pattern for this case. You can abstract the content create procedure by register different creators. Moreover, you can add preference on each creator for your own logic. Besides, I suggest you encapsulate all data related to Content just like "ContentDefinition" class from other's post.
In general, you need to know that there is always a trade off between flexibility and efficiency. Sometime your first solution is good enough:)
Ok, because I noticed a bit late that you actually wanted the ContentFrom mode as well, I've done my best to come up with a translation of your sample below my original answer
In general I use the following paradigm for cases like this. Search and replace your specific methods here and there :)
IEnumerable<T> ValueSources()
{
yield return _value?? _alternative;
yield return SimpleCalculationFromCache();
yield return ComplexCalculation();
yield return PromptUIInputFallback("Please help by entering a value for X:");
}
T EffectiveValue { get { return ValueSources().FirstOrDefault(v => v!=null); } }
Note how you can now make v!=null arbitrarily 'interesting' for your purposes.
Note also how lazy evaluation makes sure that the calculations are never done when _value or _alternative are set to 'interesting' values
Here is my initial attempt at putting your sample into this mold. Note how I added quite a lot of plumbing to make sure this actually compiles into standalone C# exe:
using System.Collections.Generic;
using System.Linq;
using System;
using T=System.String;
namespace X { public class Y
{
public static void Main(string[]args)
{
var content = Sources().FirstOrDefault(c => c); // trick: uses operator bool()
}
internal protected struct Content
{
public T Value;
public ContentFrom Mode;
//
public static implicit operator bool(Content specimen) { return specimen.Mode!=ContentFrom.None && null!=specimen.Value; }
}
private static IEnumerable<Content> Sources()
{
// mock
var Request = new { QueryString = new [] {"id"}.ToDictionary(a => a) };
if (!String.IsNullOrEmpty(Request.QueryString["id"]))
yield return new Content { Value = GetContent(Convert.ToInt64(Request.QueryString["id"])), Mode = ContentFrom.Query };
if (DefaultId != null)
yield return new Content { Value = GetContent((long) DefaultId), Mode = ContentFrom.Default };
yield return new Content();
}
public enum ContentFrom { None, Query, Default };
internal static T GetContent(long id) { return "dummy"; }
internal static readonly long? DefaultId = 42;
} }
private void InitContent()
{
Int64? id = !String.IsNullOrEmpty(Request.QueryString["id"])
? Convert.ToInt64(Request.QueryString["id"])
: null;
if (id != null && (Content = GetContent(id)) != null)
ContentMode = ContentFrom.Query;
else if(DefaultId != null && (Content = GetContent(DefaultId)) != null)
ContentMode = ContentFrom.Default;
else
ContentMode = ContentFrom.None;
}