A try-catch one liner (like "??" or ternary operator) - c#

So we have ternary operators. Great! Then there's the ?? operator, which does a coalesce over a nullable variable.
Example:
string emptyIfNull = strValue ?? "";
Question: Is it possible to implement a simple operator like this for a try-catch?
Example:
string result = CoalesceException(someExpression, "");
public static T CoalesceException<T>(expression, defaultValue)
{
try
{
return evaluate expression; // ?
}
catch
{
return defaultValue;
}
}
Is it possible to implement a method that can be used as easily as possible, or even some kind of coalesce-like operator?

You can:
public static T CoalesceException<T>(Func<T> func, T defaultValue = default(T))
{
try
{
return func();
}
catch
{
return defaultValue;
}
}
but I'm not sure this is what you want...
use:
string emptyIfError = CoalesceException(() => someExpressionThatReturnsAString, "");
for example...
string shortString = null;
string emptyIfError = CoalesceException(() => shortString.Substring(10), "");
will return "" instead of NullReferenceException
important
The function, as written, will cause the "evaluation" of defaultValue always. Meaning:
string Throws() { throw new Exception(); }
string str1 = somethingTrue == true ? "Foo" : Throws();
Here an exception won't be thrown, because Throws() won't be evalued. The same happens with the ?? operator.
string str2 = CoalesceException(() => ((string)null).ToString(), Throws());
This will cause an exception before entering in CoalesceException. Solution:
public static T CoalesceException<T>(Func<T> func, Func<T> defaultValue = null)
{
try
{
return func();
}
catch
{
return defaultValue != null ? defaultValue() : default(T);
}
}
Use:
string emptyIfError = CoalesceException(() => someExpressionThatReturnsAString, () => "");

Here a little something that I've end up, to create a One Liner TryCatch
Usage
var r = Task.TryCatch(() => _logic.Method01(param1, param2));
TryCatch definition
public static class Task
{
public static TResult TryCatch<TResult>(Func<TResult> methodDelegate)
{
try
{
return methodDelegate();
}
catch (Exception ex)
{
// .. exception handling ...
}
return default(TResult);
}
}

Related

Refactoring if statements when changing same value on different conditions

I have been working on refactoring some code and then i make something like this. Main idea is that i have couple Methods which contains implementations and they change referenced string variable name in my case.
What i don't like here is situation that in every if statement returning same variable (but with different result).
So my question does someone have better idea for eventually refactoring this? Is there any problem doing this in if statements (from logical, clean code side etc).
All my methods have ref keyword (for string variable name). Sorry for confusion!
private string GenerateNameFrom(IRow row)
{
string name = string.Empty;
if (Method1(name,row))
return name;
else if (Method2(name,row))
return name;
else if (Method3(name,row))
return name;
else return "Null";
}
Here is one way to do it:
private string GenerateNameFrom(IRow row)
{
var name = "";
return (Method1(ref name) || Method2(ref name) || Method3(ref name)) ? name : "Null";
}
Using var to instantiate the empty string, no need to write string twice.
Using || means that the first method that returns true will satisfy the condition and no other method will be executed.
Using the ?: operator for conditional return.
Note: As Matthew Watson commented, you are probably missing the ref (or out keyword - because even though a string is a reference type, it's also immutable, so if you want your methods to effect the content of the name argument, you must either send it as ref or as out, since the only way to change it's value is to assign a new string to it.
(also converted the String.Empty to "", but that's just personal preference)
The variable name will always have an empty string. as you declare and initialize just before if statement
Any how below the short way to get the same result. The Result will be same of the below code and your code:
if (Method1(name) || Method2(name) || Method3(name))
{
return name;
}
else
{
return "Null";
}
Or more specifically using ternary operator
(Method1(name) || Method2(name) || Method3(name)) ? name : "Null";
Can't see the implementation of your methods but I'm assuming something like:
public bool Method1(ref string name)
{
if (condition)
{
name = "SomeValue";
return true;
}
return false;
}
You could refactor those methods to return the updated name:
public string Method1(name)
{
if(condition)
{
return "SomeValue";
}
return null;
}
And then you could just null coalesce the method calls:
private string GenerateNameFrom(IRow row)
{
string name = string.Empty;
return Method1(name)
?? Method2(name)
?? Method3(name)
?? "Null";
}
Well all of this Method1(name) and Method2(name) doing some validation over the input string name and returning bool. In that case would suggest you to combine all those validation logic inside single method using a switch statement probably and use that method instead
I would try to avoid using ref in this case. Instead, you could make the various methods return a tuple (bool success, string value) like so:
public static (bool success, string value) Method1(string name)
{
if (name == "test")
return (true, "changed");
return (false, null);
}
public static (bool success, string value) Method2(string name)
{
if (name == "test")
return (true, "changed");
return (false, null);
}
public static (bool success, string value) Method3(string name)
{
if (name == "test")
return (true, "changed");
return (false, null);
}
Then you can write the calling code like so (it's not shorter, but it avoids ref). Whether you like this better is probably a matter of taste...
private string GenerateNameFrom(/*IRow row*/)
{
string name = string.Empty;
var result = Method1(name);
if (result.success)
return result.value;
result = Method2(name);
if (result.success)
return result.value;
result = Method3(name);
if (result.success)
return result.value;
return null;
}
Alternatively, if null can be used to indicate "no result" then just do a similar thing but checking the return value for null:
private string GenerateNameFrom(/*IRow row*/)
{
string name = string.Empty;
var result = Method1(name);
if (result != null)
return result;
result = Method2(name);
if (result != null)
return result;
return Method3(name);
}
public static string Method1(string name)
{
if (name == "test")
return "changed";
return null;
}
public static string Method2(string name)
{
if (name == "test")
return "changed";
return null;
}
public static string Method3(string name)
{
if (name == "test")
return "changed";
return null;
}

Ternary operator difficult to read

Any suggestion how to make the below query more "readable"?
var result = result
.OrderBy(a =>
(conditionA) ?
valueA :
(conditionB ? valueB :
(conditionC ?
(conditionD ?
valueC : valueD) :
valueE)));
Its difficult to read with the long code of condition and value.
There are several ways of improving the readability of your code.
Indentation
One way is to indent the code in a slightly different way, but this only helps readability a little:
var result = result.OrderBy(a =>
conditionA ? valueA :
conditionB ? valueB :
conditionC ? conditionD ? valueC :
valueD :
valueE);
if, else
You could also turn those ternary operators into a more readable chain of if, else.
var result = Result.OrderBy(a => {
if (conditionA)
{
return valueA;
}
else if (conditionB)
{
return valueB;
}
else if (conditionC)
{
if (conditionD)
{
return valueC;
}
else
{
return valueD;
}
}
else
{
return valueE;
}
});
IComparer<>
One option would be to write your own implementation of IComparer<> and pass it to the OrderBy method. I don't know what type your object is or what type the keys are in your code, so I'm going to assume string keys.
public class MyClassComparer : IComparer<MyClass>
{
public int Compare(MyClass x, MyClass y)
{
string xKey = getKey(x);
string yKey = getKey(y);
return string.Compare(xKey, yKey);
}
private string getKey(MyClass item)
{
if (item.conditionA)
{
return item.valueA;
}
else if (item.conditionB)
{
return item.valueB;
}
else if (item.conditionC)
{
if (item.conditionD)
{
return item.valueC;
}
else
{
return item.valueD;
}
}
else
{
return item.valueE;
}
}
}
Extension method
A final option would be to move your code to an extension method:
public static class MyClassExtensions
{
public static string GetSortingKey(this MyClass item)
{
if (item.conditionA)
{
return item.valueA;
}
else if (item.conditionB)
{
return item.valueB;
}
else if (item.conditionC)
{
if (item.conditionD)
{
return item.valueC;
}
else
{
return item.valueD;
}
}
else
{
return item.valueE;
}
}
}
Using the last option, your call to OrderBy is simply:
result.OrderBy(a => a.GetSortingKey())

C# Variable = new function () {};

Within C# is it possible to create a new function on the fly to define a variable?
I know that
string getResult() {
if (a)
return "a";
return "b";
}
String result = getResult();
is possible, but I'm looking for something like
String result = new string getResult() {
if (a)
return "a";
return "b";
}
Is this possible? If so, would someone demonstrate?
EDIT
It is possible
Edit: Final - Solution
This is the end result of what I barbarically hacked together
Func<string> getResult = () =>
{
switch (SC.Status)
{
case ServiceControllerStatus.Running:
return "Running";
case ServiceControllerStatus.Stopped:
return "Stopped";
case ServiceControllerStatus.Paused:
return "Paused";
case ServiceControllerStatus.StopPending:
return "Stopping";
case ServiceControllerStatus.StartPending:
return "Starting";
default:
return "Status Changing";
}
};
TrayIcon.Text = "Service Status - " + getResult();
One way to define such a function:
Func<bool, string> getResult = ( a ) => {
if (a)
return "a";
return "b";
}
You can then invoke: string foo = getResult( true );. As a delegate, it can be stored/passed and invoked when needed.
Example:
string Foo( Func<bool, string> resultGetter ){
return resultGetter( false );
}
You can also close around variables within scope:
bool a = true;
Func<string> getResult = () => {
if (a)
return "a";
return "b";
}
string result = getResult();
You want to use the inline if statement.
string result = a ? "a" : "b";
If you really want inline you can make an extension method for type String:
static class StringExtensions {
public static string ExecuteFunc(
this string str,
Func<string, string> func
) {
return func(str);
}
}
And then, when you want to use it, you do so like so:
string str = "foo";
string result = str.ExecuteFunc( s => {
switch(s){
case "a":
return "A";
default:
return "B";
}
}
);
Not sure what the scope of the variable a is in your example, but assuming that it is accessible within the scope (as it is in your example):
Func<string> getResult = () =>
{
return a ? "a" : "b";
}
Based on the solution you posted, here is a better way to do this.
Change your ServiceControllerStatus enum to add [Description] attributes:
public enum ServiceControllerStatus
{
[Description("Running")]
Running,
// ... others
}
Add the following extension method in a new static class:
public static string ToDescription(this Enum value)
{
var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}
Now you can simply write:
TrayIcon.Text = "Service Status - " SC.Status.ToDescription();

casting datareader value to a to a Nullable variable

I'm trying to run the following code but get a casting error.
How can I rewrite my code to achive the same ?
boolResult= (bool?)dataReader["BOOL_FLAG"] ?? true;
intResult= (int?)dataReader["INT_VALUE"] ?? 0;
Thanks
Use the "IsDbNull" method on the data reader... for example:
bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? null : (bool)dataReader["Bool_Flag"]
Edit
You'd need to do something akin to:
bool? nullBoolean = null;
you'd have
bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? nullBoolean : (bool)dataReader["Bool_Flag"]
Consider doing it in a function.
Here's something I used in the past (you can make this an extension method in .net 4):
public static T GetValueOrDefault<T>(SqlDataReader dataReader, System.Enum columnIndex)
{
int index = Convert.ToInt32(columnIndex);
return !dataReader.IsDBNull(index) ? (T)dataReader.GetValue(index) : default(T);
}
Edit
As an extension (not tested, but you get the idea), and using column names instead of index:
public static T GetValueOrDefault<T>(this SqlDataReader dataReader, string columnName)
{
return !dataReader.IsDBNull(dataReader[columnName]) ? (T)dataReader.GetValue(dataReader[columnName]) : default(T);
}
usage:
bool? flag = dataReader.GetValueOrDefault("BOOL_COLUMN");
There's an answer here that might be helpful:
https://stackoverflow.com/a/3308515/1255900
You can use the "as" keyword. Note the caution mentioned in the comments.
nullableBoolResult = dataReader["BOOL_FLAG"] as bool?;
Or, if you are not using nullables, as in your original post:
boolResult = (dataReader["BOOL_FLAG"] as bool?) ?? 0;
bool? boolResult = null;
int? intResult = null;
if (dataReader.IsDBNull(reader.GetOrdinal("BOOL_FLAG")) == false)
{
boolResult = dataReader.GetBoolean(reader.GetOrdinal("BOOL_FLAG"));
}
else
{
boolResult = true;
}
if (dataReader.IsDBNull(reader.GetOrdinal("INT_VALUE")) == false)
{
intResult= dataReader.GetInt32(reader.GetOrdinal("INT_VALUE"));
}
else
{
intResult = 0;
}
I'm sure I found the inspiration for this somewhere around the interweb but I can't seem to find the original source anymore. Anyway, below you find a utility class which allows to define an extension method on DataReader, like this:
public static class DataReaderExtensions
{
public static TResult Get<TResult>(this IDataReader reader, string name)
{
return reader.Get<TResult>(reader.GetOrdinal(name));
}
public static TResult Get<TResult>(this IDataReader reader, int c)
{
return ConvertTo<TResult>.From(reader[c]);
}
}
Usage:
reader.Get<bool?>("columnname")
or
reader.Get<int?>(5)
Here's the enabling utility class:
public static class ConvertTo<T>
{
// 'Factory method delegate', set in the static constructor
public static readonly Func<object, T> From;
static ConvertTo()
{
From = Create(typeof(T));
}
private static Func<object, T> Create(Type type)
{
if (!type.IsValueType) { return ConvertRefType; }
if (type.IsNullableType())
{
return (Func<object, T>)Delegate.CreateDelegate(typeof(Func<object, T>), typeof(ConvertTo<T>).GetMethod("ConvertNullableValueType", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new[] { type.GetGenericArguments()[0] }));
}
return ConvertValueType;
}
// ReSharper disable UnusedMember.Local
// (used via reflection!)
private static TElem? ConvertNullableValueType<TElem>(object value) where TElem : struct
{
if (DBNull.Value == value) { return null; }
return (TElem)value;
}
// ReSharper restore UnusedMember.Local
private static T ConvertRefType(object value)
{
if (DBNull.Value != value) { return (T)value; }
return default(T);
}
private static T ConvertValueType(object value)
{
if (DBNull.Value == value)
{
throw new NullReferenceException("Value is DbNull");
}
return (T)value;
}
}
EDIT: makes use of the IsNullableType() extension method defined like so:
public static bool IsNullableType(this Type type)
{
return
(type.IsGenericType && !type.IsGenericTypeDefinition) &&
(typeof (Nullable<>) == type.GetGenericTypeDefinition());
}
Here's my shot at an extension method. Column name semantics and falls back to default(T) when a null is encountered.
public static class DbExtensions
{
public static T ReadAs<T>(this IDataReader reader, string col)
{
object val = reader[col];
if (val is DBNull)
{
// Use the default if the column is null
return default(T);
}
return (T)val;
}
}
Here is the sample usage. Remember that despite string being a reference type, it will still fail to cast to null from a DBNull. The same is true with int?.
public Facility Bind(IDataReader reader)
{
var x = new Facility();
x.ID = reader.ReadAs<Guid>("ID");
x.Name = reader.ReadAs<string>("Name");
x.Capacity = reader.ReadAs<int?>("Capacity");
x.Description = reader.ReadAs<string>("Description");
x.Address = reader.ReadAs<string>("Address");
return x;
}
using extension method:
public static T GetValueOrDefault <T> (this SqlDataReader reader, string column) {
var isDbNull = reader[column] == DBNull.Value;
return !isDbNull ? (T) reader[column] : default (T);
}
Remember that a DBNull is not the same thing as null, so you cannot cast from one to the other. As the other poster said, you can check for DBNull using the IsDBNull() method.
Try this version. It performs some basic conversion and manages default values as well.

Generic string to enum conversion

Suppose enum:
public enum SysLogsAppTypes { None, MonitorService, MonitorTool };
and here is a function to convert from the ToString() representation back to enum:
private SysLogsAppTypes Str2SysLogsAppTypes(string str)
{
try
{
SysLogsAppTypes res = (SysLogsAppTypes)Enum
.Parse(typeof(SysLogsAppTypes), str);
if (!Enum.IsDefined(typeof(SysLogsAppTypes), res))
return SysLogsAppTypes.None;
return res;
}
catch
{
return SysLogsAppTypes.None;
}
}
Is there a way to make this Generic ??
I tried:
private T Str2enum<T>(string str)
{
try
{
T res = (T)Enum.Parse(typeof(T), str);
if (!Enum.IsDefined(typeof(T), res)) return T.None;
return res;
}
catch
{
return T.None;
}
}
but I get:
'T' is a 'type parameter', which is not valid in the given context
where there is T.None
Any help ?
Thanks
I think the default keyword is what you need:
private T Str2enum<T>(string str) where T : struct
{
try
{
T res = (T)Enum.Parse(typeof(T), str);
if (!Enum.IsDefined(typeof(T), res)) return default(T);
return res;
}
catch
{
return default(T);
}
}
Not the way you are trying it, but I use the method below to do this:
public static bool EnumTryParse<E>(string enumVal, out E resOut)
where E : struct
{
var enumValFxd = enumVal.Replace(' ', '_');
if (Enum.IsDefined(typeof(E), enumValFxd))
{
resOut = (E)Enum.Parse(typeof(E),
enumValFxd, true);
return true;
}
// ----------------------------------------
foreach (var value in
Enum.GetNames(typeof (E)).Where(value =>
value.Equals(enumValFxd,
StringComparison.OrdinalIgnoreCase)))
{
resOut = (E)Enum.Parse(typeof(E), value);
return true;
}
resOut = default(E);
return false;
}
No exceptions thrown here ...
I like to add in a defaultValue parameter for an overload of my TryParse for cases where I want a default if it can't be parsed or is null. This is most useful for parsing string.Empty or null.
Note: this implementation will revert to defaultValue if a junk value is passed in - so you may want to tweak that by throwing an exception.
public static T TryParse<T>(string value, T defaultValue) where T: struct
{
if (string.IsNullOrWhiteSpace(value))
{
return defaultValue;
}
T result;
if (Enum.TryParse<T>(value, out result))
{
return result;
}
else
{
return defaultValue; // you may want to throw exception here
}
}
}
ConverterMode mode = EnumUtils<ConverterMode>.TryParse(stringValue, ConverterMode.DefaultMode);
I know this is old, but based on a few samples, I've researched along with #Simon_Weaver's solution, this is what I have:
public static T TryParse(String value, T defaultValue) where T : struct {
if (String.IsNullOrWhiteSpace(value)) {
return defaultValue;
}
T result;
if (!Enum.TryParse(value, out result)) {
if (Enum.IsDefined(typeof (T), result) | result.ToString().Contains(",")) {
// do nothing
} else {
result = defaultValue;
}
} else {
result = defaultValue;
}
return result;
}

Categories