private struct Maybe<T>
{
private readonly T value;
private readonly bool hasValue;
private Maybe(T value)
{
this.value = value;
hasValue = true;
}
public static implicit operator Maybe<T>(T value) =>
value == null ? new Maybe<T>() : new Maybe<T>(value);
}
private static Maybe<byte> OK()
{
return 5;
}
private static Maybe<IEnumerable<byte>> NotOK()
{
var e = new[] { 1, 2, 3 }.Select(x => (byte)x);
Console.WriteLine(e.GetType().Name);
return e;
}
Fiddle (don't use): https://dotnetfiddle.net/NxAw9l
Updated fiddle: https://dotnetfiddle.net/NrARTl
Some generic type is failing for implicit conversion at above code. See the Ok() and NotOk() function calls and return types. A complex generic type is failing and I dont' understand why. I have simplified this from a function of a return type of IEnumerable<IEnumerable<T>>. This IEnumerable<T> still fails. I think If I can understand why this fails, I'd solve the real one too I suppose. Thanks for your help and time.
Here is the error message if you'd like:
Error CS0029 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<byte>' to 'Maybe<System.Collections.Generic.IEnumerable<byte>>'
Update: Returning Byte[] from the NotOK() can't work because in my real source code I have a LINQ query I have to depend on its lazy-deferred execution (i.e It has to be strictly returning IEnumerable) (see alike answer => https://stackoverflow.com/a/63880804/5917087).
The C# standard currently does not allow implicit conversions from or to interfaces.
This is a well-known problem when implementing a Maybe<T> (or Optional<T>, as it is often called) type in C#. There is an ongoing discussion about this on the C# language github forum:
https://github.com/dotnet/roslyn/issues/14186
As a workaround, you could make the Maybe<T> constructor internal and add a static non-generic helper class:
private static class Maybe
{
public static Maybe<T> From<T>(T value) =>
value == null ? new Maybe<T>() : new Maybe<T>(value);
}
which allows you to use type inference and write Maybe.From(a), which is a bit shorter than new Maybe<IEnumerable<byte>>(a).
I'm going to extend #Heinzi's answer:
You could also use extension methods:
static class MaybeExtensions
{
public static Maybe<T> AsMaybe<T>(this T value)
{
return new Maybe<T>(value);
}
public static Maybe<TResult> AsMaybe<T, TResult>(this T value)
where T : unmanaged
where TResult : unmanaged
{
return new Maybe<TResult>(Unsafe.As<T, TResult>(ref value));
}
}
And in your caller methods, you could use them like:
private static Maybe<IEnumerable<byte>> NotOK()
{
var e = new[] { 1, 2, 3 }.Select(x => (byte)x);
return e.AsMaybe();
}
private static Maybe<byte> OK()
{
return 5.AsMaybe<int, byte>();
}
// Alternatively
private static Maybe<byte> OK()
{
return ((byte)5).AsMaybe();
}
You need the AsMaybe<T, TResult> overload for value types that can convert to each other. For example when you do 5.AsMaybe() it returns Maybe<int>, if your method's return type is Maybe<byte> you will need to convert Maybe<int> to Maybe<byte>, and the overload does that for you.
Now, the type conversion operator in Maybe<T> becomes redundant. And you can use var instead of full type name:
Maybe<int> obj1 = 5; // use operator
var obj2 = 5.AsMaybe(); // use extension method
You can't define a conversion to/from an interface type, If you change your example to use List<T> rather than IEnumerable<T> it will compile - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#user-defined-conversions
Change this :
private static Maybe<IEnumerable<byte>> NotOK()
{
IEnumerable<byte> a = new byte[] { 1, 2 };
return a;
}
into this :
private static Maybe<IEnumerable<byte>> NotOK()
{
var a = new byte[] { 1, 2 };
return a;
}
The struct :
private struct Maybe<T>
{
private readonly T value;
private readonly bool hasValue;
private Maybe(T value)
{
this.value = value;
hasValue = true;
}
public static implicit operator Maybe<T>(T value)
{
return value == null ? new Maybe<T>() : new Maybe<T>(value);
}
public bool HasValue(){
return this.hasValue;
}
public T GetValue(){
return this.value;
}
}
private static Maybe<byte> OK()
{
return 5;
}
private static Maybe<IEnumerable<byte>> NotOK()
{
Byte[] a = new byte[] { 1, 2 };
Console.WriteLine(a.GetType().Name);
return a;
}
Usage :
public static void Main(string[] args){
var t1 = OK();
var t2 = NotOK();
Console.WriteLine("t1 type is " + t1.GetType().Name);
Console.WriteLine("t2 type is " + t2.GetType().Name);
if(t2.HasValue())
{
List<byte> search = t2.GetValue().Where(b => b > 0).ToList();
foreach(byte num in search){
Console.WriteLine(num);
}
}
}
The reference IEnumerable<byte> a doesn't change the type, you can continue to var or byte[] and the query with LINQ, after, see in the full example
See the full example :
https://dotnetfiddle.net/V8RHQe
IEnumerable is an interface. Compiler does not know which type to work with. Put ToList() to end of your select like follows :
private static Maybe<IEnumerable<byte>> NotOK()
{
var e = new[] { 1, 2, 3 }.Select(x => (byte)x).ToList();
Console.WriteLine(e.GetType().Name);
return e;
}
To understand what is happening try to create a method like follow in your class and watch compiler to cry :)
public static implicit operator Maybe<IEnumerable<T>>(IEnumerable<T> value)
{
return value == null ? new Maybe<IEnumerable<T>>() : new Maybe<IEnumerable<T>>(value);
}
Say I have generic value wrapper:
class Wrapper<T>
{
public T Value { get; set; }
}
And I'd like to use it as listed below (or something like this):
var wrapper = new Wrapper<Target>();
// ...
Target target = wrapper;
How is it possible using implicit operator, extension method or another approach to provide single-place null checking? As one of benefits I want to keep the following code in the single place:
if (wrapper != null)
{
return wrapper.Value;
}
return default(T);
EDIT:
I tried the operator:
public static implicit operator T(Wrapper<T> wrapper)
{
return wrapper.Value ? default(T) : wrapper.Value;
}
It's perfectly works I the way below:
var wrapper = new Wrapper<long>();
long value = wrapper;
But fails on:
var wrapper = new Wrapper<IEnumerable<long>>();
IEnumerable<long> value = wrapper;
Compiler says it is not possible to convert from Wrapper<IEnumerable<long>> to IEnumerable<long>. Any ideas?
You can use an implicit operator:
public static implicit operator T(Wrapper<T> value)
{
return value == null ? default(T) : value.Value;
}
EDIT:
As #ChrisSinclair has pointed out, this doesn't work when T is interface the only solution a can think of is using an extension method like:
public static T SafeGetValue<T>(this Wrapper<T> value)
{
return value == null ? default(T) : value.Value;
}
And then:
IEnumerable<long> value = wrapper.SafeGetValue();
return wrapper.Value ?? default(T);
The null-checking could be done in the generic wrapper itself as follows.
class Wrapper<T>
{
private T _value;
public T Value
{
get
{
return _value ?? default(T);
}
set
{
_value = value;
};
}
}
This question already has answers here:
Optional delegates in C# [duplicate]
(4 answers)
Closed 9 years ago.
I have an implementation of a Maybe / Option class in c#. Basic implementation is
public delegate Maybe<TOutput> Converter<in TInput, out TOutput>(TInput input);
public delegate TOutput ElseDelegate<out TOutput>();
public delegate Maybe<TOutput> ElseDelegate2<out TOutput>();
public interface Maybe<out TResult> : IEnumerable<TResult>
{
Maybe<B> Bind<B>(Converter<TResult, B> f);
TResult Value();
bool IsSome();
}
public static class Maybe
{
public static Maybe<T> None<T>()
{
return new None<T>();
}
}
public interface INone<out TResult> : Maybe<TResult>
{
}
public interface ISome<out TResult> : Maybe<TResult>
{
}
public struct None<TResult> : INone<TResult>
{
public IEnumerator<TResult> GetEnumerator()
{ yield break; }
IEnumerator IEnumerable.GetEnumerator()
{ yield break; }
public bool IsSome() { return false; }
public Maybe<TOutput> Bind<TOutput>(Converter<TResult, TOutput> f)
{
return new None<TOutput>();
}
public TResult Value()
{
throw new IndexOutOfRangeException("None has no value");
}
}
public struct Some<TResult> : Maybe<TResult>
{
private TResult _Value;
public Some(TResult value)
{
_Value = value;
}
public IEnumerator<TResult> GetEnumerator()
{ yield return _Value; }
IEnumerator IEnumerable.GetEnumerator()
{ yield return _Value; }
public bool IsSome() { return true; }
public Maybe<TOutput> Bind<TOutput>(Converter<TResult, TOutput> f)
{
return f(_Value);
}
public TResult Value()
{
return this._Value;
}
}
#endregion
with a bunch of extension methods I have not included here. This all works
fine. However a standard pattern I would like to implement is below,
using Maybe to implement optional parameter defaults as in F#
void DoSomeCalc
( Maybe<double> x = Maybe.None<double>()
, Maybe<double> y = Maybe.None<double>()
)
{
this.X = x.Else( ()=> CalculateDefaultX() );
this.Y = y.Else( ()=> CalculateDefaultY() );
}
so I can do
DoSomeCalc(x:10)
or
DoSomeCalc(y:20)
where Else provides a value if None is available. However
this is all nice in theory but C# optional parameters
must be compile time constants which completely screws
this pattern.
Can anybody suggest a fix that will keep the intent of
the pattern without introducing nullables or nulls here?
Is there anyway I can create a compile time constant to
represent None here that will work with my above
implementation of Maybe?
No, there's nothing you can do here. Your parameter type is a reference type, which means the only constant values available are null and string literals. (Obviously string literals aren't useful in your case; I only mention them as the only kind of non-null reference type constant.)
One option would be to make Maybe<T> a struct instead of an interface, with the default value the "none" value. This would then be basically the same as Nullable<T> but without the constraint that T had to be a non-nullable value type. You could then use:
void DoSomeCalc(Maybe<double> x = default(Maybe<double>),
Maybe<double> y = default(Maybe<double>))
Sample code showing all of this:
using System;
struct Maybe<T>
{
private readonly bool hasValue;
public bool HasValue { get { return hasValue; } }
private readonly T value;
public T Value
{
get
{
if (!hasValue)
{
throw new InvalidOperationException();
}
return value;
}
}
public Maybe(T value)
{
this.hasValue = true;
this.value = value;
}
public static implicit operator Maybe<T>(T value)
{
return new Maybe<T>(value);
}
}
class Test
{
static void DoSomeCalc(Maybe<double> x = default(Maybe<double>),
Maybe<double> y = default(Maybe<double>))
{
Console.WriteLine(x.HasValue ? "x = " + x.Value : "No x");
Console.WriteLine(y.HasValue ? "y = " + y.Value : "No y");
}
static void Main()
{
Console.WriteLine("First call");
DoSomeCalc(x: 10);
Console.WriteLine("Second call");
DoSomeCalc(y: 20);
}
}
Obviously you'd want to add more functionality to Maybe<T>, such as overriding ToString and Equals, but you get the general idea. You can still have a non-generic Maybe class with factory methods too, of course.
You can use null internally to mean Maybe.None<double>(). E.g.:
double DoSomeCalc
( Maybe<double> x = null
, Maybe<double> y = null
)
{
x = x ?? Maybe.None<double>();
y = y ?? Maybe.None<double>();
this.X = x.Else( ()=> CalculateDefaultX() );
this.Y = y.Else( ()=> CalculateDefaultY() );
}
It is not ideal as you have to document somewhere in comments that passing null means "use a particular default".
i have written a generic method to convert int to Enum String, getting an error. Please Help Thanx.
public static string GetStringEquiValentOFEnumFromString<T>(int enumVal)
where T : struct
{
if(Enum.IsDefined(typeof(T),enumVal))
{
return ((T)enumVal).ToString(); ///Error: Cannot convert type 'int' to 'T'
}
return null;
}
I think you can use Enum.ToObject:
public static string GetStringEquiValentOFEnumFromString<T>(int enumVal)
where T : struct
{
if (Enum.IsDefined(typeof(T), enumVal))
{
return Enum.ToObject(typeof (T), enumVal).ToString();
}
}
http://msdn.microsoft.com/en-us/library/system.enum.toobject.aspx
This ought to work:
public static string GetStringEquiValentOFEnumFromString<T>(int enumVal)
where T : struct
{
if(Enum.IsDefined(typeof(T),enumVal))
{
return ((T)(object)enumVal).ToString();
}
return null;
}
You're seeing this error because generic type arguments cannot be constrained to the enum type in C#. Since your constraint only says it has to be a value type the compiler cannot guarantee that enumVal will be convertible to T and gives a compile time error.
To get around this you can explicitly define the enum type in the function:
public static string GetStringFromValue(this MyEnum enum, int val) {
if (Enum.IsDefined(typeof(MyEnum), val)) {
return ((MyEnum) val).ToString();
}
return null;
}
Or you can use something like Jon Skeet's UnconstrainedMelody library which rewrites your code at the bytecode level to enforce the enum constraint (callable from another assembly).
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attr = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
if (attr.Length > 0)
{
output = attr[0].Value;
}
return output;
}
}
StringEnum is a class which have (GetStringValue) method to get the string value.
public enum CampaignRequestType { [StringValue("None")] None = 0, [StringValue("Pharmacy Cards")] Pharmacy_Cards = 1,[StringValue("Prospect Campaign")] Prospect_Campaign = 2,[StringValue("Tradeshow/Advertising")] Tradeshow_Advertising = 3 }
its a enum...
string item = StringEnum.GetStringValue((Enumeration.CampaignRequestType)updateRequestStatus.RequestType_Code);
here (Enumeration.CampaignRequestType) is my enumeration and updateRequestStatus.RequestType_Code is data base field int type
i cast int value to enumeration type
I'm wanting to parse a string into a nullable int in C#. ie. I want to get back either the int value of the string or null if it can't be parsed.
I was kind of hoping that this would work
int? val = stringVal as int?;
But that won't work, so the way I'm doing it now is I've written this extension method
public static int? ParseNullableInt(this string value)
{
if (value == null || value.Trim() == string.Empty)
{
return null;
}
else
{
try
{
return int.Parse(value);
}
catch
{
return null;
}
}
}
Is there a better way of doing this?
EDIT: Thanks for the TryParse suggestions, I did know about that, but it worked out about the same. I'm more interested in knowing if there is a built-in framework method that will parse directly into a nullable int?
int.TryParse is probably a tad easier:
public static int? ToNullableInt(this string s)
{
int i;
if (int.TryParse(s, out i)) return i;
return null;
}
Edit #Glenn int.TryParse is "built into the framework". It and int.Parse are the way to parse strings to ints.
You can do this in one line, using the conditional operator and the fact that you can cast null to a nullable type (two lines, if you don't have a pre-existing int you can reuse for the output of TryParse):
Pre C#7:
int tempVal;
int? val = Int32.TryParse(stringVal, out tempVal) ? tempVal : (int?)null;
With C#7's updated syntax that allows you to declare an output variable in the method call, this gets even simpler.
int? val = Int32.TryParse(stringVal, out var tempVal) ? tempVal : (int?)null;
[Updated to use modern C# as per #sblom's suggestion]
I had this problem and I ended up with this (after all, an if and 2 returns is soo long-winded!):
int? ToNullableInt (string val)
=> int.TryParse (val, out var i) ? (int?) i : null;
On a more serious note, try not to mix int, which is a C# keyword, with Int32, which is a .NET Framework BCL type - although it works, it just makes code look messy.
C# >= 7.1
var result = int.TryParse(foo, out var f) ? f : default;
See C# language versioning to ascertain what language version your project supports
Glenn Slaven: I'm more interested in knowing if
there is a built-in framework method
that will parse directly into a
nullable int?
There is this approach that will parse directly to a nullable int (and not just int) if the value is valid like null or empty string, but does throw an exception for invalid values so you will need to catch the exception and return the default value for those situations:
public static T Parse<T>(object value)
{
try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToString()); }
catch { return default(T); }
}
This approach can still be used for non-nullable parses as well as nullable:
enum Fruit { Orange, Apple }
var res1 = Parse<Fruit>("Apple");
var res2 = Parse<Fruit?>("Banana");
var res3 = Parse<int?>("100") ?? 5; //use this for non-zero default
var res4 = Parse<Unit>("45%");
NB: There is an IsValid method on the converter you can use instead of capturing the exception (thrown exceptions does result in unnecessary overhead if expected). Unfortunately it only works since .NET 4 but there's still an issue where it doesn't check your locale when validating correct DateTime formats, see bug 93559.
Old topic, but how about:
public static int? ParseToNullableInt(this string value)
{
return String.IsNullOrEmpty(value) ? null : (int.Parse(value) as int?);
}
I like this better as the requriement where to parse null, the TryParse version would not throw an error on e.g. ToNullableInt32(XXX). That may introduce unwanted silent errors.
Try this:
public static int? ParseNullableInt(this string value)
{
int intValue;
if (int.TryParse(value, out intValue))
return intValue;
return null;
}
I feel my solution is a very clean and nice solution:
public static T? NullableParse<T>(string s) where T : struct
{
try
{
return (T)typeof(T).GetMethod("Parse", new[] {typeof(string)}).Invoke(null, new[] { s });
}
catch (Exception)
{
return null;
}
}
This is of course a generic solution which only require that the generics argument has a static method "Parse(string)". This works for numbers, boolean, DateTime, etc.
You can forget all other answers - there is a great generic solution:
http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/
This allows you to write very clean code like this:
string value = null;
int? x = value.ConvertOrDefault();
and also:
object obj = 1;
string value = null;
int x = 5;
if (value.TryConvert(out x))
Console.WriteLine("TryConvert example: " + x);
bool boolean = "false".ConvertOrDefault();
bool? nullableBoolean = "".ConvertOrDefault();
int integer = obj.ConvertOrDefault();
int negativeInteger = "-12123".ConvertOrDefault();
int? nullableInteger = value.ConvertOrDefault();
MyEnum enumValue = "SecondValue".ConvertOrDefault();
MyObjectBase myObject = new MyObjectClassA();
MyObjectClassA myObjectClassA = myObject.ConvertOrDefault();
I would suggest following extension methods for string parsing into int value with ability to define default value in case parsing is not possible:
public static int ParseInt(this string value, int defaultIntValue = 0)
{
return int.TryParse(value, out var parsedInt) ? parsedInt : defaultIntValue;
}
public static int? ParseNullableInt(this string value)
{
if (string.IsNullOrEmpty(value))
return null;
return value.ParseInt();
}
The following should work for any struct type. It is based off code by Matt Manela from MSDN forums. As Murph points out the exception handling could be expensive compared to using the Types dedicated TryParse method.
public static bool TryParseStruct<T>(this string value, out Nullable<T> result)
where T: struct
{
if (string.IsNullOrEmpty(value))
{
result = new Nullable<T>();
return true;
}
result = default(T);
try
{
IConvertible convertibleString = (IConvertible)value;
result = new Nullable<T>((T)convertibleString.ToType(typeof(T), System.Globalization.CultureInfo.CurrentCulture));
}
catch(InvalidCastException)
{
return false;
}
catch (FormatException)
{
return false;
}
return true;
}
These were the basic test cases I used.
string parseOne = "1";
int? resultOne;
bool successOne = parseOne.TryParseStruct<int>(out resultOne);
Assert.IsTrue(successOne);
Assert.AreEqual(1, resultOne);
string parseEmpty = string.Empty;
int? resultEmpty;
bool successEmpty = parseEmpty.TryParseStruct<int>(out resultEmpty);
Assert.IsTrue(successEmpty);
Assert.IsFalse(resultEmpty.HasValue);
string parseNull = null;
int? resultNull;
bool successNull = parseNull.TryParseStruct<int>(out resultNull);
Assert.IsTrue(successNull);
Assert.IsFalse(resultNull.HasValue);
string parseInvalid = "FooBar";
int? resultInvalid;
bool successInvalid = parseInvalid.TryParseStruct<int>(out resultInvalid);
Assert.IsFalse(successInvalid);
I'm more interested in knowing if there is a built-in framework method that will parse directly into a nullable int?
There isn't.
This solution is generic without reflection overhead.
public static Nullable<T> ParseNullable<T>(string s, Func<string, T> parser) where T : struct
{
if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(s.Trim())) return null;
else return parser(s);
}
static void Main(string[] args)
{
Nullable<int> i = ParseNullable("-1", int.Parse);
Nullable<float> dt = ParseNullable("3.14", float.Parse);
}
I felt I should share mine which is a bit more generic.
Usage:
var result = "123".ParseBy(int.Parse);
var result2 = "123".ParseBy<int>(int.TryParse);
Solution:
public static class NullableParse
{
public static Nullable<T> ParseBy<T>(this string input, Func<string, T> parser)
where T : struct
{
try
{
return parser(input);
}
catch (Exception exc)
{
return null;
}
}
public delegate bool TryParseDelegate<T>(string input, out T result);
public static Nullable<T> ParseBy<T>(this string input, TryParseDelegate<T> parser)
where T : struct
{
T t;
if (parser(input, out t)) return t;
return null;
}
}
First version is a slower since it requires a try-catch but it looks cleaner. If it won't be called many times with invalid strings, it is not that important.
If performance is an issue, please note that when using TryParse methods, you need to specify the type parameter of ParseBy as it can not be inferred by the compiler. I also had to define a delegate as out keyword can not be used within Func<>, but at least this time compiler does not require an explicit instance.
Finally, you can use it with other structs as well, i.e. decimal, DateTime, Guid, etc.
I found and adapted some code for a Generic NullableParser class. The full code is on my blog Nullable TryParse
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace SomeNamespace
{
/// <summary>
/// A parser for nullable types. Will return null when parsing fails.
/// </summary>
/// <typeparam name="T"></typeparam>
///
public static class NullableParser<T> where T : struct
{
public delegate bool TryParseDelegate(string s, out T result);
/// <summary>
/// A generic Nullable Parser. Supports parsing of all types that implements the tryParse method;
/// </summary>
/// <param name="text">Text to be parsed</param>
/// <param name="result">Value is true for parse succeeded</param>
/// <returns>bool</returns>
public static bool TryParse(string s, out Nullable<T> result)
{
bool success = false;
try
{
if (string.IsNullOrEmpty(s))
{
result = null;
success = true;
}
else
{
IConvertible convertableString = s as IConvertible;
if (convertableString != null)
{
result = new Nullable<T>((T)convertableString.ToType(typeof(T),
CultureInfo.CurrentCulture));
success = true;
}
else
{
success = false;
result = null;
}
}
}
catch
{
success = false;
result = null;
}
return success;
}
}
}
public static void Main(string[] args)
{
var myString = "abc";
int? myInt = ParseOnlyInt(myString);
// null
myString = "1234";
myInt = ParseOnlyInt(myString);
// 1234
}
private static int? ParseOnlyInt(string s)
{
return int.TryParse(s, out var i) ? i : (int?)null;
}
The cleaner way would be to write a separate function or extension method, but if you just want a one-liner:
string s;
int? i = s == null ? (int?)null : int.Parse(s);
You should never use an exception if you don't have to - the overhead is horrible.
The variations on TryParse solve the problem - if you want to get creative (to make your code look more elegant) you could probably do something with an extension method in 3.5 but the code would be more or less the same.
Using delegates, the following code is able to provide reusability if you find yourself needing the nullable parsing for more than one structure type. I've shown both the .Parse() and .TryParse() versions here.
This is an example usage:
NullableParser.TryParseInt(ViewState["Id"] as string);
And here is the code that gets you there...
public class NullableParser
{
public delegate T ParseDelegate<T>(string input) where T : struct;
public delegate bool TryParseDelegate<T>(string input, out T outtie) where T : struct;
private static T? Parse<T>(string input, ParseDelegate<T> DelegateTheParse) where T : struct
{
if (string.IsNullOrEmpty(input)) return null;
return DelegateTheParse(input);
}
private static T? TryParse<T>(string input, TryParseDelegate<T> DelegateTheTryParse) where T : struct
{
T x;
if (DelegateTheTryParse(input, out x)) return x;
return null;
}
public static int? ParseInt(string input)
{
return Parse<int>(input, new ParseDelegate<int>(int.Parse));
}
public static int? TryParseInt(string input)
{
return TryParse<int>(input, new TryParseDelegate<int>(int.TryParse));
}
public static bool? TryParseBool(string input)
{
return TryParse<bool>(input, new TryParseDelegate<bool>(bool.TryParse));
}
public static DateTime? TryParseDateTime(string input)
{
return TryParse<DateTime>(input, new TryParseDelegate<DateTime>(DateTime.TryParse));
}
}
I realise this is an old topic, but can't you simply:
(Nullable<int>)int.Parse(stringVal);
?
I've come up with this one, which has satisfied my requirements (I wanted my extension method to emulate as close as possible the return of the framework's TryParse, but without try{} catch{} blocks and without the compiler complaining about inferring a nullable type within the framework method)
private static bool TryParseNullableInt(this string s, out int? result)
{
int i;
result = int.TryParse(s, out i) ? (int?)i : null;
return result != null;
}
I suggest code bellow. You may work with exception, when convert error occured.
public static class Utils {
public static bool TryParse<Tin, Tout>(this Tin obj, Func<Tin, Tout> onConvert, Action<Tout> onFill, Action<Exception> onError) {
Tout value = default(Tout);
bool ret = true;
try {
value = onConvert(obj);
}
catch (Exception exc) {
onError(exc);
ret = false;
}
if (ret)
onFill(value);
return ret;
}
public static bool TryParse(this string str, Action<int?> onFill, Action<Exception> onError) {
return Utils.TryParse(str
, s => string.IsNullOrEmpty(s) ? null : (int?)int.Parse(s)
, onFill
, onError);
}
public static bool TryParse(this string str, Action<int> onFill, Action<Exception> onError) {
return Utils.TryParse(str
, s => int.Parse(s)
, onFill
, onError);
}
}
Use this extension method in code (fill int? Age property of a person class):
string ageStr = AgeTextBox.Text;
Utils.TryParse(ageStr, i => person.Age = i, exc => { MessageBox.Show(exc.Message); });
OR
AgeTextBox.Text.TryParse(i => person.Age = i, exc => { MessageBox.Show(exc.Message); });