Finding MinMax values and returning a tuple as a result
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
I was coding some tooling stuff when I started to ponder whether the best return type for a Range / MinMax method applied on a IEnumerable method.
I am using the value the C# 7 Tuples like below, but tempted to create my own class with readonly fields.
public static (TSource Min, TSource Max) MinMax<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
using (var sourceIterator = source.GetEnumerator())
if (!sourceIterator.MoveNext())
throw new InvalidOperationException("Sequence contains no elements");
var max = sourceIterator.Current;
var min = sourceIterator.Current;
while (sourceIterator.MoveNext())
var candidate = sourceIterator.Current;
if (comparer.LeftStrictlyLesserThanRight(candidate, min))
min = candidate;
if (comparer.LeftStrictlyGreaterThanRight(candidate, max))
max = candidate;
return (min, max);
Utilities are defined as below:
internal static class ComparerExtensions
public static bool LeftStrictlyGreaterThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) > 0;
public static bool LeftStrictlyLesserThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) < 0;
What do you think is the best, knowing that creating a reference type would bring some additional allocations and GC work (I mean that was the whole point to have struct-like tuples in C# 7). What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
I don't know maybe it's just me and my over-defensive coding style and bad experience using Python where coders are considered as "adults"?
c# .net extension-methods
add a comment |Â
up vote
5
down vote
favorite
I was coding some tooling stuff when I started to ponder whether the best return type for a Range / MinMax method applied on a IEnumerable method.
I am using the value the C# 7 Tuples like below, but tempted to create my own class with readonly fields.
public static (TSource Min, TSource Max) MinMax<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
using (var sourceIterator = source.GetEnumerator())
if (!sourceIterator.MoveNext())
throw new InvalidOperationException("Sequence contains no elements");
var max = sourceIterator.Current;
var min = sourceIterator.Current;
while (sourceIterator.MoveNext())
var candidate = sourceIterator.Current;
if (comparer.LeftStrictlyLesserThanRight(candidate, min))
min = candidate;
if (comparer.LeftStrictlyGreaterThanRight(candidate, max))
max = candidate;
return (min, max);
Utilities are defined as below:
internal static class ComparerExtensions
public static bool LeftStrictlyGreaterThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) > 0;
public static bool LeftStrictlyLesserThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) < 0;
What do you think is the best, knowing that creating a reference type would bring some additional allocations and GC work (I mean that was the whole point to have struct-like tuples in C# 7). What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
I don't know maybe it's just me and my over-defensive coding style and bad experience using Python where coders are considered as "adults"?
c# .net extension-methods
3
LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
â t3chb0t
Apr 14 at 22:23
I'm not sure why you're only considering (value) tuples and classes? An immutable result without extra allocations sounds like a struct with readonly fields to me.
â Pieter Witvoet
Apr 14 at 22:47
@PieterWitvoet agreed, always wondering why MS didn't vote for a read-only (value type) tuples
â Ehouarn Perret
Apr 14 at 22:49
@t3chb0t hm alright will change that, thanks!
â Ehouarn Perret
Apr 14 at 22:49
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
I was coding some tooling stuff when I started to ponder whether the best return type for a Range / MinMax method applied on a IEnumerable method.
I am using the value the C# 7 Tuples like below, but tempted to create my own class with readonly fields.
public static (TSource Min, TSource Max) MinMax<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
using (var sourceIterator = source.GetEnumerator())
if (!sourceIterator.MoveNext())
throw new InvalidOperationException("Sequence contains no elements");
var max = sourceIterator.Current;
var min = sourceIterator.Current;
while (sourceIterator.MoveNext())
var candidate = sourceIterator.Current;
if (comparer.LeftStrictlyLesserThanRight(candidate, min))
min = candidate;
if (comparer.LeftStrictlyGreaterThanRight(candidate, max))
max = candidate;
return (min, max);
Utilities are defined as below:
internal static class ComparerExtensions
public static bool LeftStrictlyGreaterThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) > 0;
public static bool LeftStrictlyLesserThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) < 0;
What do you think is the best, knowing that creating a reference type would bring some additional allocations and GC work (I mean that was the whole point to have struct-like tuples in C# 7). What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
I don't know maybe it's just me and my over-defensive coding style and bad experience using Python where coders are considered as "adults"?
c# .net extension-methods
I was coding some tooling stuff when I started to ponder whether the best return type for a Range / MinMax method applied on a IEnumerable method.
I am using the value the C# 7 Tuples like below, but tempted to create my own class with readonly fields.
public static (TSource Min, TSource Max) MinMax<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
using (var sourceIterator = source.GetEnumerator())
if (!sourceIterator.MoveNext())
throw new InvalidOperationException("Sequence contains no elements");
var max = sourceIterator.Current;
var min = sourceIterator.Current;
while (sourceIterator.MoveNext())
var candidate = sourceIterator.Current;
if (comparer.LeftStrictlyLesserThanRight(candidate, min))
min = candidate;
if (comparer.LeftStrictlyGreaterThanRight(candidate, max))
max = candidate;
return (min, max);
Utilities are defined as below:
internal static class ComparerExtensions
public static bool LeftStrictlyGreaterThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) > 0;
public static bool LeftStrictlyLesserThanRight<T>(this IComparer<T> comparer, T left, T right)
return comparer.Compare(left, right) < 0;
What do you think is the best, knowing that creating a reference type would bring some additional allocations and GC work (I mean that was the whole point to have struct-like tuples in C# 7). What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
I don't know maybe it's just me and my over-defensive coding style and bad experience using Python where coders are considered as "adults"?
c# .net extension-methods
edited Apr 15 at 10:18
t3chb0t
32k54195
32k54195
asked Apr 14 at 21:47
Ehouarn Perret
1857
1857
3
LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
â t3chb0t
Apr 14 at 22:23
I'm not sure why you're only considering (value) tuples and classes? An immutable result without extra allocations sounds like a struct with readonly fields to me.
â Pieter Witvoet
Apr 14 at 22:47
@PieterWitvoet agreed, always wondering why MS didn't vote for a read-only (value type) tuples
â Ehouarn Perret
Apr 14 at 22:49
@t3chb0t hm alright will change that, thanks!
â Ehouarn Perret
Apr 14 at 22:49
add a comment |Â
3
LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
â t3chb0t
Apr 14 at 22:23
I'm not sure why you're only considering (value) tuples and classes? An immutable result without extra allocations sounds like a struct with readonly fields to me.
â Pieter Witvoet
Apr 14 at 22:47
@PieterWitvoet agreed, always wondering why MS didn't vote for a read-only (value type) tuples
â Ehouarn Perret
Apr 14 at 22:49
@t3chb0t hm alright will change that, thanks!
â Ehouarn Perret
Apr 14 at 22:49
3
3
LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.â t3chb0t
Apr 14 at 22:23
LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.â t3chb0t
Apr 14 at 22:23
I'm not sure why you're only considering (value) tuples and classes? An immutable result without extra allocations sounds like a struct with readonly fields to me.
â Pieter Witvoet
Apr 14 at 22:47
I'm not sure why you're only considering (value) tuples and classes? An immutable result without extra allocations sounds like a struct with readonly fields to me.
â Pieter Witvoet
Apr 14 at 22:47
@PieterWitvoet agreed, always wondering why MS didn't vote for a read-only (value type) tuples
â Ehouarn Perret
Apr 14 at 22:49
@PieterWitvoet agreed, always wondering why MS didn't vote for a read-only (value type) tuples
â Ehouarn Perret
Apr 14 at 22:49
@t3chb0t hm alright will change that, thanks!
â Ehouarn Perret
Apr 14 at 22:49
@t3chb0t hm alright will change that, thanks!
â Ehouarn Perret
Apr 14 at 22:49
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
4
down vote
accepted
What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
We cannot prevent everything and sometimes it's just easier and quicker to use the simplest solution like tuples in this case. You can always switch to something more complex if necessary but it's good to start by following the YAGNI principle.
I was coding some tooling stuff
It depnds on what kind of tooling stuff your are coding. If this is some tiny helper then I'd go with tuples. If I was creatng a general purpose library then and big type would be better. You could validate the parameters and make sure that min <= max
etc.
As an example you can take a look at my generic Range.cs
that is supported by expressions to be able to work with any comparable type BinaryOperation.cs
.
Regarding your ComparerExtensions
I start with what I already said in my comment: LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
I also find the extensions are not intuitive. They should be extensions on the T
and not on the comparer like that:
x.LessThen(y)
and/or
x.LessThen(y, comparer)
It's more natural (and shorter) to write than
comparer.LeftLessThenRight(x, y)
This means you can create two pairs of these extensions for each operation.
public static bool LessThen<T>(this T x, T y) where T : IComparable<T>
public static bool LessThen<T>(this T x, T y, IComparer<T> comparer)
one that uses the interface IComparable
implemented by T
and the other one that uses a custom comparer.
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
add a comment |Â
up vote
1
down vote
Can use else if
on the second
I do not like the name LeftStrictlyLesserThanRight but you could just use that and flop the candidate, max
for LeftStrictlyLesserThanRight.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
We cannot prevent everything and sometimes it's just easier and quicker to use the simplest solution like tuples in this case. You can always switch to something more complex if necessary but it's good to start by following the YAGNI principle.
I was coding some tooling stuff
It depnds on what kind of tooling stuff your are coding. If this is some tiny helper then I'd go with tuples. If I was creatng a general purpose library then and big type would be better. You could validate the parameters and make sure that min <= max
etc.
As an example you can take a look at my generic Range.cs
that is supported by expressions to be able to work with any comparable type BinaryOperation.cs
.
Regarding your ComparerExtensions
I start with what I already said in my comment: LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
I also find the extensions are not intuitive. They should be extensions on the T
and not on the comparer like that:
x.LessThen(y)
and/or
x.LessThen(y, comparer)
It's more natural (and shorter) to write than
comparer.LeftLessThenRight(x, y)
This means you can create two pairs of these extensions for each operation.
public static bool LessThen<T>(this T x, T y) where T : IComparable<T>
public static bool LessThen<T>(this T x, T y, IComparer<T> comparer)
one that uses the interface IComparable
implemented by T
and the other one that uses a custom comparer.
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
add a comment |Â
up vote
4
down vote
accepted
What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
We cannot prevent everything and sometimes it's just easier and quicker to use the simplest solution like tuples in this case. You can always switch to something more complex if necessary but it's good to start by following the YAGNI principle.
I was coding some tooling stuff
It depnds on what kind of tooling stuff your are coding. If this is some tiny helper then I'd go with tuples. If I was creatng a general purpose library then and big type would be better. You could validate the parameters and make sure that min <= max
etc.
As an example you can take a look at my generic Range.cs
that is supported by expressions to be able to work with any comparable type BinaryOperation.cs
.
Regarding your ComparerExtensions
I start with what I already said in my comment: LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
I also find the extensions are not intuitive. They should be extensions on the T
and not on the comparer like that:
x.LessThen(y)
and/or
x.LessThen(y, comparer)
It's more natural (and shorter) to write than
comparer.LeftLessThenRight(x, y)
This means you can create two pairs of these extensions for each operation.
public static bool LessThen<T>(this T x, T y) where T : IComparable<T>
public static bool LessThen<T>(this T x, T y, IComparer<T> comparer)
one that uses the interface IComparable
implemented by T
and the other one that uses a custom comparer.
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
add a comment |Â
up vote
4
down vote
accepted
up vote
4
down vote
accepted
What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
We cannot prevent everything and sometimes it's just easier and quicker to use the simplest solution like tuples in this case. You can always switch to something more complex if necessary but it's good to start by following the YAGNI principle.
I was coding some tooling stuff
It depnds on what kind of tooling stuff your are coding. If this is some tiny helper then I'd go with tuples. If I was creatng a general purpose library then and big type would be better. You could validate the parameters and make sure that min <= max
etc.
As an example you can take a look at my generic Range.cs
that is supported by expressions to be able to work with any comparable type BinaryOperation.cs
.
Regarding your ComparerExtensions
I start with what I already said in my comment: LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
I also find the extensions are not intuitive. They should be extensions on the T
and not on the comparer like that:
x.LessThen(y)
and/or
x.LessThen(y, comparer)
It's more natural (and shorter) to write than
comparer.LeftLessThenRight(x, y)
This means you can create two pairs of these extensions for each operation.
public static bool LessThen<T>(this T x, T y) where T : IComparable<T>
public static bool LessThen<T>(this T x, T y, IComparer<T> comparer)
one that uses the interface IComparable
implemented by T
and the other one that uses a custom comparer.
What bothers me with the tuple is that fields are not readonly and we cannot prevent users of the method to mess up and break flow.
We cannot prevent everything and sometimes it's just easier and quicker to use the simplest solution like tuples in this case. You can always switch to something more complex if necessary but it's good to start by following the YAGNI principle.
I was coding some tooling stuff
It depnds on what kind of tooling stuff your are coding. If this is some tiny helper then I'd go with tuples. If I was creatng a general purpose library then and big type would be better. You could validate the parameters and make sure that min <= max
etc.
As an example you can take a look at my generic Range.cs
that is supported by expressions to be able to work with any comparable type BinaryOperation.cs
.
Regarding your ComparerExtensions
I start with what I already said in my comment: LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.
I also find the extensions are not intuitive. They should be extensions on the T
and not on the comparer like that:
x.LessThen(y)
and/or
x.LessThen(y, comparer)
It's more natural (and shorter) to write than
comparer.LeftLessThenRight(x, y)
This means you can create two pairs of these extensions for each operation.
public static bool LessThen<T>(this T x, T y) where T : IComparable<T>
public static bool LessThen<T>(this T x, T y, IComparer<T> comparer)
one that uses the interface IComparable
implemented by T
and the other one that uses a custom comparer.
edited Apr 15 at 10:18
answered Apr 15 at 10:13
t3chb0t
32k54195
32k54195
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
add a comment |Â
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
Thanks for the guidelines, really well appreciated! I thought about that too, I mean switching to an extension method for <T> and putting the comparer as the last parameter, more natural as you said. Funny that you mentioned the Range class even though in my case I already have one with iteration options and intersection check with others ranges but I got the gist. Thanks again!
â Ehouarn Perret
Apr 15 at 14:29
add a comment |Â
up vote
1
down vote
Can use else if
on the second
I do not like the name LeftStrictlyLesserThanRight but you could just use that and flop the candidate, max
for LeftStrictlyLesserThanRight.
add a comment |Â
up vote
1
down vote
Can use else if
on the second
I do not like the name LeftStrictlyLesserThanRight but you could just use that and flop the candidate, max
for LeftStrictlyLesserThanRight.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
Can use else if
on the second
I do not like the name LeftStrictlyLesserThanRight but you could just use that and flop the candidate, max
for LeftStrictlyLesserThanRight.
Can use else if
on the second
I do not like the name LeftStrictlyLesserThanRight but you could just use that and flop the candidate, max
for LeftStrictlyLesserThanRight.
edited Apr 15 at 8:48
answered Apr 14 at 23:32
paparazzo
4,8131730
4,8131730
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192068%2ffinding-minmax-values-and-returning-a-tuple-as-a-result%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
3
LeftStrictlyLesserThanRight
- I think virtually all programming languages call this just less-than and its counterpart less-than-or-equal.â t3chb0t
Apr 14 at 22:23
I'm not sure why you're only considering (value) tuples and classes? An immutable result without extra allocations sounds like a struct with readonly fields to me.
â Pieter Witvoet
Apr 14 at 22:47
@PieterWitvoet agreed, always wondering why MS didn't vote for a read-only (value type) tuples
â Ehouarn Perret
Apr 14 at 22:49
@t3chb0t hm alright will change that, thanks!
â Ehouarn Perret
Apr 14 at 22:49