just to throw some code out there
string answer = "hotel"
if (answer == "house"|| answer == "hotel" || answer =="appartment")
{
DoSomething()
}
I was wondering if there was some way to shorten it to
string answer = "hotel"
if (answer == "house"|| "hotel" || "appartment")
{
DoSomething()
}
I am aware of the switch statement
switch (answer)
{
case "house":
case "hotel":
case "appartment": DoSomething();
break;
default :DoNothing();
}
I am just wondering if there is some syntax sugar like what I described above.
It is possible to use some syntactic sugar for this:
if((new[]{"house", "hotel", "apartment"}).Contains(answer))
{
}
Note that this will create a new array on the fly, so will potentially be more expensive than just the Boolean checks.
You could use an array and use Contains.
So in your example:
string answer = "hotel";
string[] acceptable = new string[]{"house", "hotel", "appartment"};
if (acceptable.Contains(answer)){
DoSomething();
}
public static bool Any<T>(T item, params T[] items)
{
return items.Contains(item);
}
Usage:
if (Any(6, 1, 2, 3, 4, 5, 6, 7))
{
// 6 == 6
}
if (Any("Hi", "a", "cad", "asdf", "hi"))
{
}
else
{
// "Hi" != "hi" and from anything else.
}
Or:
public string[] items = new string[] {"a", "cad", "asdf", "hi"};
...
if (Any("Hi", items))
{
Works just as well.
}
You can also have more advanced comparison. For example, if you wanted:
if (person.Name == p1.Name ||
person.Name == p2.Name ||
person.Name == p3.Name ||
person.Name == p4.Name ||
person.Name == p5.Name || ...)
{
}
You can have:
public static bool Any<T>(T item, Func<T, T, bool> equalityChecker, params T[] items)
{
return items.Any(x => equalityChecker(item, x));
}
And do:
if (Any(person, (per1, per2) => p1.Name == p2.Name, p1, p2, p3, p4, p5, ...)
{
}
EDIT
If you insist, you can make it, of course, an extension method:
public static bool Any<T>(this T item, params T[] items)
{
return items.Contains(item);
}
Usage:
var b = 6.Any(4, 5, 6, 7); // true
And the same logic of adding the keyword "item" in the signature goes for the overload with the equalityChecker.
Create a Global List and just check it in any method.
List<string> validAnswers = new List<string> {"house", "house1", "apartment"};
if (validAnswers.Contains(answer))
DoSomething();
In this case your List will not be generated every time answer is checked
Only thing I can think of is to work with a list or array:
List<String> words = new List<String> { "house", "hotel", "appartment" };
String answer = "house";
if (words.Contains(answer))
{
DoSomething();
}
You can do like
if(new string[]{"house","hotel","appartment"}.Contains(asnwer))
{
...
}
or
if(new List<string>(){"house","hotel","appartment"}.Any(x=>x == answer)
{
}
Can add this like an extension method too, and use...
Consider adding an extension method that will accept any strings...
string answer = "hotel"
if (answer.EqualsAny("house", "hotel", "appartment"))
{
DoSomething()
}
// Extending the thought to another version
if (answer.EqualsAll("house", "hotel", "appartment"))
{
DoSomething()
}
public static class Extensions
{
public static bool EqualsAny(this string value, params string[] compareAgainst)
{
foreach (var element in compareAgainst)
{
if(value == element)
return true;
}
return false;
}
public static bool EqualsAll(this string value, params string[] compareAgainst)
{
foreach (var element in compareAgainst)
{
if(value != element)
return false;
}
return true;
}
}
If your comparison parameters are fixed, you can opt for ENUM with Flags. Ref MSDN.
Then you can have the desired behavior.
You can also refer to this post
I normally use a switch statement in this case, but as already said in a few answers above you can put the results in an list or array and check it that way.
I would use an extension method like this:
public static bool In<T>(this T item, params T[] items)
{
return items.Contains(item);
}
Use it like this:
if ("hotel".In("house", "hotel", "apartment"))
or
if (1.In(1,2))
Related
I'm trying to do a simple comparison on two objects, simply to track changes on saving to the database, I have the below code which works perfectly on simple objects.
public static List<Variance> Compare<T>(this T original, T current)
{
var variances = new List<Variance>();
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
{
var v = new Variance
{
PropertyName = property.Name,
Original = property.GetValue(original),
Current = property.GetValue(current)
};
if (v.Original == null && v.Current == null)
{
continue;
}
if ((v.Original == null && v.Current != null) || (v.Original != null && v.Current == null))
{
variances.Add(v);
continue;
}
if (!v.Original.Equals(v.Current))
{
variances.Add(v);
}
}
return variances;
}
but if T is a list the equals need to be changed to a SequenceEqual and I can't think of a way to convert T to the correct list type to do the SequenceEqual check.
Although it's not impossible to use SequenceEqual here, it'd involve either dynamic like in Jasper Kent's answer, or quite a lot of reflection code, I'll outline what you'll need to do if you were using reflection:
check if both the objects are IEnumerable<T>.
get the Type of both objects, and then get the type parameter T as a Type as well
get the method SequenceEquals from Enumerable as a MethodInfo. This involves using LINQ to find the overload with two parameters.
call MakeGenericMethod with T.
Invoke the MethodInfo
I wouldn't want to read, or write that code... Using dynamic is fine I guess, though some people have different opinions...
So here's a third way: I suggest you write your own SequenceEqual method that takes IEnumerables (the non-generic version):
private static bool SequenceEqual(IEnumerable first, IEnumerable second) {
IEnumerator e1 = first.GetEnumerator();
IEnumerator e2 = second.GetEnumerator();
try {
// adapted from https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,63644a881e976b52,references
while (e1.MoveNext())
{
if (!(e2.MoveNext() && e1.Current.Equals(e2.Current))) return false;
}
if (e2.MoveNext()) return false;
return true;
} finally {
if (e1 is IDisposable d1) {
d1.Dispose();
}
if (e2 is IDisposable d2) {
d2.Dispose();
}
}
}
Then you can just check whether the objects are IEnumerable:
if (v.Original is Enumerable e1 &&
v.Current is Enumerable e2 &&
!SequenceEqual(e1, e2))
{
variances.Add(v);
}
I think the solution you want is to use dynamic overloading.
I've cut this solution down from yours to get to the nub of it. The call to SwitchEquals() is the equivalent of your v.Original.Equals(v.Current).
static bool SwitchEquals<T>(IEnumerable<T> listA, IEnumerable<T> listB)
{
Console.WriteLine("Doing Sequential Equals");
return true; // Do your sequential equal here
}
static bool SwitchEquals(object objA, object objB)
{
Console.WriteLine("Doing equals");
return objA.Equals(objB); // This is your original equals
}
static void Compare<T>(T original, T current)
{
// Using dynamic means the decision between the tow SwitchEquals methods is made
// At runtime, when the system knows if we have a collection
if (SwitchEquals ((dynamic)original,(dynamic) current))
Console.WriteLine("Match");
else
Console.WriteLine("No match");
}
static void Main(string[] args)
{
Compare(4,5);
Compare (new int[] { 4, 3 }, new int[] { 4, 4 });
}
I'm trying to write a function that populates strings with the contents of an array, or sets them to null. The number of strings is can vary and I don't want to add requirements like them all being part of the same array or class.
In C# you cannot combine param and out. Therefore the only way to do this seems to be to overload the method like this:
public void ParseRemainders(string[] remainders, out string p1)
{
p1 = null;
if ((remainders != null) && (remainders.Length > 0))
p1 = remainders[0];
}
public void ParseRemainders(string[] remainders, out string p1, out string p2)
{
p1 = null;
p2 = null;
if (remainders != null)
{
ParseRemainders(remainders, out p1);
if (remainders.Length > 1)
p2 = remainders[1];
}
}
public void ParseRemainders(string[] remainders, out string p1, out string p2, out string p3)
{
p1 = null;
p2 = null;
p3 = null;
if (remainders != null)
{
ParseRemainders(remainders, out p1, out p2);
if (remainders.Length > 2)
p3 = remainders[2];
}
}
.... and on forever ....
How can I avoid all this code duplication, ideally accepting an arbitrary number of parameters?
Edit: This is useful because you could do, say, ParseRemainders(remainders, out inputFileName, out outputFileName, out configFileName) and then avoid having to manually do
if (remainder.Length > 0) inputFileName = remainder[0];
if (remainder.Length > 1) outputFileName = remainder[1];
if (remainder.Length > 2) configFileName = remainder[2];
...
Sorry if this wasn't clear, I had a specific goal in mind which I why I didn't simply return a List<>.
Conclusion: Thanks to Botond Balázs for the answer, particularly the hint that this is called "array destructuring". As they point out, and as this question confirms, it is not possible in the current version of C#: Destructuring assignment - object properties to variables in C#
I would take a different approach than any of the answers so far.
static class Extensions {
public static SafeArrayReader<T> MakeSafe<T>(this T[] items)
{
return new SafeArrayReader<T>(items);
}
}
struct SafeArrayReader<T>
{
private T[] items;
public SafeArrayReader(T[] items) { this.items = items; }
public T this[int index]
{
get
{
if (items == null || index < 0 || index >= items.Length)
return default(T);
return items[index];
}
}
}
There, now you have an array that gives you a default value instead of throwing:
var remainder = GetRemainders().MakeSafe();
var input = remainder[0];
var output = remainder[1];
var config = remainder[2];
Easy peasy. You have a problem with the semantics of a data type? Make a better data type that encapsulates the desired semantics.
If I understand you correctly, your use case would look like this:
var remainders = new[] { "a", "b", "c" };
string a, b, c;
ParseRemainders(remainders, a, b, c); // after this, a == "a", b == "b" and c == "c"
The feature you want to have in C# is called array destructuring, like in JavaScript:
var remainders = ["a", "b", "c"];
var [a, b, c] = remainders; // after this, a == "a", b == "b" and c == "c"
Unfortunately, as far as I know,
this cannot be solved in a general way using C#.
C# 7 will have tuple destructuring though.
Well, you can change your method to something like
public IEnumerable<string> ParseRemainders(string[] remainders)
{
var result = new List<string>();
///... your logic here, fill list with your strings according to your needs
return result;
}
Andys approach is fine but i'd return a string[] because it should have the same size as the input array and also return null if the input array was null:
public string[] ParseRemainders(string[] remainders)
{
if(remainders == null) return null;
var parsed = new string[remainders.Length];
for(int i = 0; i < remainders.Length; i++)
parsed[i] = ParseRemainder(remainders[i]);
return parsed;
}
To clarify what ParseRemainder(different method for a single string) does:
public string ParseRemainder(string remainder)
{
// parsing logic here...
return "the parsing result of remainder";
}
For completeness, this is how you can do this kind of thing in C#7 (Visual Studio 2017):
string[] test = { "One", "Two", "Three", "Four", "Five" };
var (a, b, c) = (test[0], test[2], test[4]);
Debug.Assert(a == "One");
Debug.Assert(b == "Three");
Debug.Assert(c == "Five");
The important line here is var (a, b, c) = (test[0], test[2], test[4]); which shows you the shorthand way of assigning several different variables from some elements of an array.
However, this doesn't help with the assigning of null if the array isn't long enough. You could get around that problem by writing a helper class:
public sealed class ElementsOrNull<T> where T: class
{
readonly IList<T> array;
public ElementsOrNull(IList<T> array)
{
this.array = array;
}
public T this[int index]
{
get
{
if (index < array.Count)
return array[index];
return null;
}
}
}
And then:
string[] test = { "One", "Two", "Three", "Four", "Five" };
var t = new ElementsOrNull<string>(test);
var (a, b, c) = (t[0], t[2], t[6]);
Debug.Assert(a == "One");
Debug.Assert(b == "Three");
Debug.Assert(c == null);
But I'm sure most people (myself included) will think that's more trouble than it's worth.
I think this gets pretty close to what you want. It doesn't need C# 7, works with any data element type, and isn't limited to arrays. You may want to pick better names than ValueReader/ReadValue, though.
static class Extensions
{
public static ValueReader<T> ReadValue<T>(this IEnumerable<T> source, out T value)
{
var result = new ValueReader<T>(source);
result.ReadValue(out value);
return result;
}
}
class ValueReader<T>
{
IEnumerator<T> _enumerator;
public ValueReader(IEnumerable<T> source)
{
if (source == null) source = new T[0];
_enumerator = source.GetEnumerator();
}
public ValueReader<T> ReadValue(out T value)
{
bool hasNext = _enumerator.MoveNext();
value = hasNext ? _enumerator.Current : default(T);
return this;
}
}
static class TestApp
{
public static void Main()
{
var remainders = new string[] { "test1", "test2", "test3" };
string inputFileName, outputFileName, configFileName, willBeSetToNull;
remainders
.ReadValue(out inputFileName)
.ReadValue(out outputFileName)
.ReadValue(out configFileName)
.ReadValue(out willBeSetToNull);
}
}
Just use an index in the array, eg:
remainers[0]; //same as p1
remainers[1]; //same as p2
remainers[2]; //same as p3
From your description I'm guessing your use case would be something similar to:
public void SomeMethod( ... )
{
string p1;
string p2;
....
ParseRemainders(string[] remainders, out string p1, out string p2);
...
}
public void SomeOtherMethod( ... )
{
string p1;
string p2;
string p3;
....
ParseRemainders(string[] remainders, out string p1, out string p2, out string p3);
...
}
You don't need to return strings this way. As already pointed out in other answers / comments, you can simply return an array of strings:
string[] ParseRemainders(string[] remainders)
{
var result = new string[remainder.Length];
result[0] = //whatever p1 would be
result[1] = //whatever p2 would be
//etc.
}
And you would use it like this:
public void SomeMethod( ... )
{
....
var parsed = ParseRemainders(string[] remainders);
string p1 = parsed[0];
string p2 = parsed[1];
....
}
That looks a lot better.
It feels like you're trying to over-complicate a simple null check, just go back to basics and keep it simple:
public string GetRemainder(string[] remainders, int index)
{
if ((remainders != null) && (remainders.Length > index))
return remainders[index];
return null;
}
Usage:
var inputFileName = GetRemainder(remainder, 0);
var outputFileName = GetRemainder(remainder, 1);
var configFileName = GetRemainder(remainder, 2);
After a long search i have my first question.
I have this piece of code:
var strings = new MyStringList { "orange", "APPLE", "grape", "pear" };
foreach (var item in strings.Where(s => s.Length == 5))
{
txtLog.WriteLine(item);
}
And a public class:
public class MyStringList : List<string>
{
public IEnumerable<string> Where(Predicate<string> filter)
{
return this.Select(s => filter(s) ? s.ToUpper() : s);
}
}
Is there a way to rewrite the return statement in an If Else construction?
I came to something like this, only the if gives an error:
if (this.Select(s=> filter(s)))
{
return this.Select(s => s.ToUpper());
}
else
{
return this.Select(s => s);
}
Since your filter works on a single item, you have to iterate through your collection first. During iteration there is no longer any need to use Select() instead you use yield return to dynamically return an iterator.
public IEnumerable<string> Where(Predicate<string> filter)
{
foreach (var s in this)
{
if (filter(s))
yield return s.ToUpper();
else
yield return s;
}
}
Im working with 2 List, i want to see if the main contains the same types. The 2 lists do not need to contain the same count or order, just have all of the matching Types. I know this is very possible with Linq, however i cannot use that.
private static bool ContentsMatch(List<Type> list1, List<Type> list2)
{
if (list1.Count != list2.Count)
return false;
for (int i = 0; i < list1.Count; i++)
{
if (!list1[i].Equals(list2[i]))
return false;
}
return true;
}
The above method i tried will only return true if they are in the same order.
Code for algorithm provided in the comments.
Does not depend on order or count or duplicate items. Also generic and abstracted.
bool IsSameSet<T>(IEnumerable<T> l1, IEnumerable<T> l2)
{
return IsSubSet(l1, l2) && IsSubSet(l2, l1);
}
bool IsSubSet<T>(IEnumerable<T> l1, IEnumerable<T> l2)
{
var lookup = new Dictionary<T, bool>();
foreach (var e in l1)
lookup[e] = true;
foreach (var e in l2)
if (!lookup.ContainsKey(e))
return false;
return true;
}
Usage:
Type[] l1 = { typeof(object), typeof(int), typeof(long), typeof(object) };
Type[] l2 = { typeof(int), typeof(long), typeof(object) };
var result = IsSameSet(l1, l2);
Console.WriteLine(result); // prints true
Exercise for the user:
Add an additional parameter to provide an IEqualityComparer<T> to be passed to the dictionary.
To compare any user defined customized types, we need to override Equals & GetHashCode.
Below is the code snippet you could refer to :
public class CustomizedDataType
{
private int field1;
private string field2;
public CustomizedDataType(int field1,string field2)
{
this.field1 = field1;
this.field2 = field2;
}
public override bool Equals(object obj)
{
CustomizedDataType dataType = obj as CustomizedDataType;
if (this.field1 == dataType.field1 && this.field2 == dataType.field2)
{
return true;
}
return false;
}
public override int GetHashCode()
{
return (this.field1.GetHashCode() + this.field2.GetHashCode());
}
Sample code to execute :
static void Main(string[] args)
{
//Test Data
List<CustomizedDataType> dataTypeContaineer1 = new List<CustomizedDataType>();
dataTypeContaineer1.Add(new CustomizedDataType(10,"Test10"));
dataTypeContaineer1.Add(new CustomizedDataType(11, "Test11"));
dataTypeContaineer1.Add(new CustomizedDataType(12, "Test12"));
//Test Data
List<CustomizedDataType> dataTypeContaineer2 = new List<CustomizedDataType>();
dataTypeContaineer2.Add(new CustomizedDataType(100, "Test10"));
dataTypeContaineer2.Add(new CustomizedDataType(11, "Test11"));
dataTypeContaineer2.Add(new CustomizedDataType(12, "Test120"));
//Checking if both the list contains the same types.
if (dataTypeContaineer1.GetType() == dataTypeContaineer2.GetType())
{
//Checking if both the list contains the same count
if (dataTypeContaineer1.Count == dataTypeContaineer2.Count)
{
//Checking if both the list contains the same data.
for (int index = 0; index < dataTypeContaineer1.Count; index++)
{
if(!dataTypeContaineer1[index].Equals(dataTypeContaineer2[index]))
{
Console.WriteLine("Mismatch # Index {0}", index);
}
}
}
}
}
Output :
You can use the C# keyword 'is' to see if an object is compatible with a given type.
http://msdn.microsoft.com/en-us/library/vstudio/scekt9xw.aspx
Assuming you mean that that two List<T> both have matching T, you could use:
private static Boolean MatchingBaseType(IEnumerable a, IEnumerable b)
{
return GetIListBaseType(a) == GetIListBaseType(b);
}
private static Type GetIListBaseType(IEnumerable a)
{
foreach (Type interfaceType in a.GetType().GetInterfaces())
{
if (interfaceType.IsGenericType &&
(interfaceType.GetGenericTypeDefinition() == typeof(IList<>) ||
interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
interfaceType.GetGenericTypeDefinition() == typeof(ICollection<>))
)
{
return interfaceType.GetGenericArguments()[0];
}
}
return default(Type);
}
You say count doesn't matter (though you're checking .Count()--why?) But this should return if the two lists have the same types in them.
I'd like a general solution but as an example, assume i have an IEnumerable<string>, where some can be parsed as integers, and some cannot.
var strings = new string[] { "1", "2", "notint", "3" };
Obviously if i did Select(s => int.Parse(s, temp)) it'd throw an exception when enumerated.
In this case i could do .All(s => int.TryParse(s, out temp)) first, however i want a general solution where i don't have to enumerate the IEnumerable twice.
Ideally i'd like to be able to do the following, which calls my magic exception skipping method:
// e.g. parsing strings
var strings = new string[] { "1", "2", "notint", "3" };
var numbers = strings.Select(s => int.Parse(s)).SkipExceptions();
// e.g. encountering null object
var objects = new object[] { new object(), new object(), null, new object() }
var objecttostrings = objects.Select(o => o.ToString()).SkipExceptions();
// e.g. calling a method that could throw
var myClassInstances = new MyClass[] { new MyClass(), new MyClass(CauseMethodToThrow:true) };
var myClassResultOfMethod = myClassInstances.Select(mci => mci.MethodThatCouldThrow()).SkipExceptions();
How can i write the SkipExceptions() extension method?
Some great answers for a SelectSkipExceptions() method, however i wonder if a SkipExceptions() method could be created, along the same lines as AsParallel().
How about this (you might want to give this special Select Extension a better name)
public static IEnumerable<TOutput> SelectIgnoringExceptions<TInput, TOutput>(
this IEnumerable<TInput> values, Func<TInput, TOutput> selector)
{
foreach (var item in values)
{
TOutput output = default(TOutput);
try
{
output = selector(item);
}
catch
{
continue;
}
yield return output;
}
}
Edit5
Added a using statement, thanks for the suggestion in comments
public static IEnumerable<T> SkipExceptions<T>(
this IEnumerable<T> values)
{
using(var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch
{
continue;
}
if(next) yield return enumerator.Current;
}
}
}
However this relies on the incoming IEnumerable not already being created (and therefore already having thrown Exceptions) as a list by the preceding Function. E.g. this would probably not work if you call it like this: Select(..).ToList().SkipExceptions()
Create a TryParseInt method that returns a Nullable<int>:
int? TryParseInt(string s)
{
int i;
if (int.TryParse(s, out i))
return i;
return null;
}
And use it in your query like that:
var numbers = strings.Select(s => TryParseInt(s))
.Where(i => i.HasValue)
.Select(i => i.Value);
See also this article by Bill Wagner, which presents a very similar case.
Now, i don't think you can write something like a generic SkipExceptions method, because you would catch the exception too late, and it would end the Select loop... But you could probably write a SelectSkipException method:
public static IEnumerable<TResult> SelectSkipExceptions<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return source.SelectSkipExceptionsIterator(selector);
}
private static IEnumerable<TResult> SelectSkipExceptionsIterator<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
foreach(var item in source)
{
TResult value = default(TResult);
try
{
value = selector(item);
}
catch
{
continue;
}
yield return value;
}
}
Even the accepted answer may not be "general" enough. What if some day you find that you need to know what exceptions occurred?
The following extension
static class EnumeratorHelper {
//Don't forget that GetEnumerator() call can throw exceptions as well.
//Since it is not easy to wrap this within a using + try catch block with yield,
//I have to create a helper function for the using block.
private static IEnumerable<T> RunEnumerator<T>(Func<IEnumerator<T>> generator,
Func<Exception, bool> onException)
{
using (var enumerator = generator())
{
if (enumerator == null)
yield break;
for (; ; )
{
//You don't know how to create a value of T,
//and you don't know weather it can be null,
//but you can always have a T[] with null value.
T[] value = null;
try
{
if (enumerator.MoveNext())
value = new T[] { enumerator.Current };
}
catch (Exception e)
{
if (onException(e))
continue;
}
if (value != null)
yield return value[0];
else
yield break;
}
}
}
public static IEnumerable<T> WithExceptionHandler<T>(this IEnumerable<T> orig,
Func<Exception, bool> onException)
{
return RunEnumerator(() =>
{
try
{
return orig.GetEnumerator();
}
catch (Exception e)
{
onException(e);
return null;
}
}, onException);
}
}
will help. Now you can add SkipExceptions:
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> orig){
return orig.WithExceptionHandler(orig, e => true);
}
By using different onException callback, you can do different things
Break the iteration but ignore the exception: e => false
Try to continue iteration: e => true
Log the exception, etc
Here's a small complete program to demonstrate an answer inspired by the maybe monad. You might want to change the name of the 'Maybe' class, as it is inspired by rather than actually being a 'Maybe' as defined in other languages.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestMaybe
{
class Program
{
static void Main(string[] args)
{
var strings = new string[] { "1", "2", "notint", "3" };
var ints = strings.Select(s => new Maybe<string, int>(s, str => int.Parse(str))).Where(m => !m.nothing).Select(m => m.value);
foreach (var i in ints)
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
public class Maybe<T1, T2>
{
public readonly bool nothing;
public readonly T2 value;
public Maybe(T1 input, Func<T1, T2> map)
{
try
{
value = map(input);
}
catch (Exception)
{
nothing = true;
}
}
}
}
Edit: depending on the needs of your code, you might also want nothing set to true if the result of map(input) is null.
This is the same answer as Thomas's, but with a lambda & LINQ expression. +1 for Thomas.
Func<string, int?> tryParse = s =>
{
int? r = null;
int i;
if (int.TryParse(s, out i))
{
r = i;
}
return r;
};
var ints =
from s in strings
let i = tryParse(s)
where i != null
select i.Value;
You could just chain the Where and Select method together.
var numbers = strings.Where(s =>
{
int i;
return int.TryParse(s, out i);
}).Select(int.Parse);
The use of the Where method effectively removes the need for you to write your own SkipExceptions method, because this is basically what you are doing.