What are your favorite extension methods for C#? (codeplex.com/extensionoverflow)

130,964

Solution 1

public static bool In<T>(this T source, params T[] list)
{
  if(null==source) throw new ArgumentNullException("source");
  return list.Contains(source);
}

Allows me to replace:

if(reallyLongIntegerVariableName == 1 || 
    reallyLongIntegerVariableName == 6 || 
    reallyLongIntegerVariableName == 9 || 
    reallyLongIntegerVariableName == 11)
{
  // do something....
}

and

if(reallyLongStringVariableName == "string1" || 
    reallyLongStringVariableName == "string2" || 
    reallyLongStringVariableName == "string3")
{
  // do something....
}

and

if(reallyLongMethodParameterName == SomeEnum.Value1 || 
    reallyLongMethodParameterName == SomeEnum.Value2 || 
    reallyLongMethodParameterName == SomeEnum.Value3 || 
    reallyLongMethodParameterName == SomeEnum.Value4)
{
  // do something....
}

With:

if(reallyLongIntegerVariableName.In(1,6,9,11))
{
      // do something....
}

and

if(reallyLongStringVariableName.In("string1","string2","string3"))
{
      // do something....
}

and

if(reallyLongMethodParameterName.In(SomeEnum.Value1, SomeEnum.Value2, SomeEnum.Value3, SomeEnum.Value4)
{
  // do something....
}

Solution 2

I have various extension methods in my MiscUtil project (full source is available there - I'm not going to repeat it here). My favourites, some of which involve other classes (such as ranges):

Date and time stuff - mostly for unit tests. Not sure I'd use them in production :)

var birthday = 19.June(1976);
var workingDay = 7.Hours() + 30.Minutes();

Ranges and stepping - massive thanks to Marc Gravell for his operator stuff to make this possible:

var evenNaturals = 2.To(int.MaxValue).Step(2);
var daysSinceBirth = birthday.To(DateTime.Today).Step(1.Days());

Comparisons:

var myComparer = ProjectionComparer.Create(Person p => p.Name);
var next = myComparer.ThenBy(p => p.Age);
var reversed = myComparer.Reverse();

Argument checking:

x.ThrowIfNull("x");

LINQ to XML applied to anonymous types (or other types with appropriate properties):

// <Name>Jon</Name><Age>32</Age>
new { Name="Jon", Age=32}.ToXElements();
// Name="Jon" Age="32" (as XAttributes, obviously)
new { Name="Jon", Age=32}.ToXAttributes()

Push LINQ - would take too long to explain here, but search for it.

Solution 3

string.Format shortcut:

public static class StringExtensions
{
    // Enable quick and more natural string.Format calls
    public static string F(this string s, params object[] args)
    {
        return string.Format(s, args);
    }
}

Example:

var s = "The co-ordinate is ({0}, {1})".F(point.X, point.Y);

For quick copy-and-paste go here.

Don't you find it more natural to type "some string".F("param") instead of string.Format("some string", "param") ?

For a more readable name, try one of these suggestion:

s = "Hello {0} world {1}!".Fmt("Stack", "Overflow");
s = "Hello {0} world {1}!".FormatBy("Stack", "Overflow");
s = "Hello {0} world {1}!".FormatWith("Stack", "Overflow");
s = "Hello {0} world {1}!".Display("Stack", "Overflow");
s = "Hello {0} world {1}!".With("Stack", "Overflow");

..

Solution 4

Are these any use?

public static bool CoinToss(this Random rng)
{
    return rng.Next(2) == 0;
}

public static T OneOf<T>(this Random rng, params T[] things)
{
    return things[rng.Next(things.Length)];
}

Random rand;
bool luckyDay = rand.CoinToss();
string babyName = rand.OneOf("John", "George", "Radio XBR74 ROCKS!");

Solution 5

public static class ComparableExtensions
{
  public static bool Between<T>(this T actual, T lower, T upper) where T : IComparable<T>
  {
    return actual.CompareTo(lower) >= 0 && actual.CompareTo(upper) < 0;
  }
}

Example:

if (myNumber.Between(3,7))
{
  // ....
}
Share:
130,964
beam022
Author by

beam022

I'm primarily interested in good software design, patterns, TDD, DDD and Microsoft technologies C#, .net, MSSQL.

Updated on November 19, 2020

Comments

  • beam022
    beam022 over 3 years

    Let's make a list of answers where you post your excellent and favorite extension methods.

    The requirement is that the full code must be posted and a example and an explanation on how to use it.

    Based on the high interest in this topic I have setup an Open Source Project called extensionoverflow on Codeplex.

    Please mark your answers with an acceptance to put the code in the Codeplex project.

    Please post the full sourcecode and not a link.

    Codeplex News:

    24.08.2010 The Codeplex page is now here: http://extensionoverflow.codeplex.com/

    11.11.2008 XmlSerialize / XmlDeserialize is now Implemented and Unit Tested.

    11.11.2008 There is still room for more developers. ;-) Join NOW!

    11.11.2008 Third contributer joined ExtensionOverflow, welcome to BKristensen

    11.11.2008 FormatWith is now Implemented and Unit Tested.

    09.11.2008 Second contributer joined ExtensionOverflow. welcome to chakrit.

    09.11.2008 We need more developers. ;-)

    09.11.2008 ThrowIfArgumentIsNull in now Implemented and Unit Tested on Codeplex.

  • Jon Skeet
    Jon Skeet over 15 years
    It's certainly short - but will be unreadable to any new members of your team.
  • mckurt
    mckurt over 15 years
    readability is the only reason that I wouldn't use this, apart from that its a good idea
  • chakrit
    chakrit over 15 years
    I think readability matters more in the grander scheme of your code than a few shorthand statements that could be quickly looked up/asked.
  • Jon Skeet
    Jon Skeet over 15 years
    Personally I'd like a separate Formatter object, which the BCL could parse the pattern of once and reuse. That would increase readability and performance. I've asked the BCL team - we'll see...
  • Jon Skeet
    Jon Skeet over 15 years
    I'd suggest renaming "SetTime" to "WithTime" as it's not actually setting it in the existing value. Nice otherwise though.
  • chakrit
    chakrit over 15 years
    That's nice! You should put it up on Google Code or CodePlex so I can send you some patches :-) I promise it'll be readable :-P
  • cfeduke
    cfeduke over 15 years
    I've found myself writing something very similar.
  • cfeduke
    cfeduke over 15 years
    I like this too, Jon has it in his, and I use something similar from Umbrella, could stand to drop "ArgumentIs" part.
  • cfeduke
    cfeduke over 15 years
    Yup, same ToInt64, ToFloat, etc. You can eliminate the if and knock it down to one return if you like.
  • chakrit
    chakrit over 15 years
    Wasn't that already done? Since this is just another way to call into the BCL?
  • Jon Skeet
    Jon Skeet over 15 years
    chakrit: No - because every time you format, the BCL will have to parse the format string. Format strings usually remain constant throughout the course of a program's lifetime - why parse them more than once each?
  • cfeduke
    cfeduke over 15 years
    This is nice, I remember in my last 1.1 framework writing a series of BetweenInt32, BetweenDateTime, etc.
  • Vyas Bharghava
    Vyas Bharghava over 15 years
    What does this accomplish except for adding one more method call... For me it does not look readable at all.
  • beam022
    beam022 over 15 years
    It pops up with a password thing. Just press cancel.
  • Pure.Krome
    Pure.Krome over 15 years
    Yeah! this is a kewl extension method too :)
  • chakrit
    chakrit over 15 years
    @Jon_Skeet I see. That'd add more value to the method as well hehe.
  • chakrit
    chakrit over 15 years
    I don't understand... If you have used string.format before, then you'd certainly can quickly guess that it's a string.format call. And a quick goto definition would tell you that. If you don't like it, just name it 'Format' or whatever you like. Take a look at the '%' format operator in Python.
  • Andrew Bullock
    Andrew Bullock over 15 years
    You should use Decimal for currency else you'll get rounding issues
  • mackenir
    mackenir over 15 years
    12 fairly basic extension methods. I'm a bit underwhelmed by mono-rocks.
  • mackenir
    mackenir over 15 years
    DateTime.Now.First() - first what? It's only apparent from the sample code.
  • mackenir
    mackenir over 15 years
    (I'm talking about the released version, not the one you need to use source-control to get)
  • chakrit
    chakrit over 15 years
    @Rune I did, I just provided this as example. I have my own version of util extensions lib too.
  • chakrit
    chakrit over 15 years
    ah ha I used to have a bunch of these as well. But it was kind of too large when you want string.ToInt32 double.ToInt32 float.ToInt32.. blah blah I think I've overused it a bit :-)
  • chakrit
    chakrit over 15 years
    You could do that in 2 linq select-where statements. Does that count as BCL?
  • cfeduke
    cfeduke over 15 years
    Yes. (Obligatory comment character limit here.)
  • beam022
    beam022 over 15 years
    Very nice. But agree that the names could be a lot better.
  • Jon Skeet
    Jon Skeet over 15 years
    @bovium: You can already see the code. Follow the link in the first sentence - full source is there.
  • Steve Hiner
    Steve Hiner over 15 years
    I love this one but I'm trying to decide if it's right to make the bounds check inclusive on the min value but exclusive on the max value. I wonder if that would be confusing. 5.Between(5,10) is true but 5.Between(1,5) is false. Not even sure that a companion Within method would help. Thougts?
  • Alan
    Alan over 15 years
    Hm, what exactly was wrong with this one? I don't mind the downvote, but I'd honestly like to know if it's not supposed to work or something.
  • Joel Mueller
    Joel Mueller over 15 years
    On the IsNullOrEmpty one I'd hate to call it on a million-item enumerator. It would loop through all million items just to tell me it's not empty. Better: return iEnumerable == null || !iEnumerable.Any();
  • Pure.Krome
    Pure.Krome over 15 years
    Oh dude - awesomesauce! i never knew that! cheers heaps dude. (my post above, edited.)
  • Joel Mueller
    Joel Mueller over 15 years
    Glad you like it. One thing - Any() returns a boolean, so <= 0 probably won't compile. If the enumerable is empty, Any() will return false. This font makes it hard to see, but my original example has an exclamation point in front of the call to Any.
  • Damir Zekić
    Damir Zekić over 15 years
    You cannot call it "Format" or else it won't compile. I name it "Inject" when I use similar extension
  • hangy
    hangy over 15 years
    This should also work as an extension method for IDataReader.
  • beam022
    beam022 over 15 years
    @Jon Skeet. Can I use the code and put it in the Codeplex project?
  • beam022
    beam022 over 15 years
    This is not using Extension Methods. Its just a static class.
  • Jon Skeet
    Jon Skeet over 15 years
    @bovium: I'd rather do it myself, putting it on code.google.com and manage the project myself, if you don't mind. Obviously you're within the licence to put it on Codeplex if you keep the appropriate attribution, but I'd rather sort it out myself soon unless you're desperate :)
  • beam022
    beam022 over 15 years
    @Jon Skeet. Its put under the MIT license free of use for everybody. Commercially or open source. Why not join forces and make an extension methods library for the public.
  • beam022
    beam022 over 15 years
    @Pure.Krome Can I use the code in the codeplex project. And do you not want to become a contributer to that project?
  • Timothy Khouri
    Timothy Khouri over 15 years
    Rename "F" to "FormatWith" and it'll be better. The functionality is good, but the name needs to be fixed.
  • user1709101
    user1709101 over 15 years
    Anyone can use it - Help yourself
  • Armstrongest
    Armstrongest over 15 years
    To make that an extension method change: static public bool CompareFiles(string path1, string path2) to static public bool IsSameFileAs(this string path1, string path2); then use like: if (file1.IsSameFileAs(file2)
  • Pure.Krome
    Pure.Krome over 15 years
    Personally, i'm not a fan of code that does try / catch to determine the outcome. Try / catch should be used for errors that occur outside of the intended logic, IMO. hmmmmm
  • chakrit
    chakrit over 15 years
    @bovium sure... @Atomiton I think.. but I don't know Ruby well enough to be sure.
  • chakrit
    chakrit over 15 years
    This enum-parsing scenario comes up all the time... gotta put this in my lib :-)
  • Joel Mueller
    Joel Mueller over 15 years
    Actually, make the "this" parameter of type IDataRecord for maximum compatibility. In my version of this, I have an overload that takes an ordinal, which the fieldName version calls. Saves the "GetOrdinal" followed by a lookup by name.
  • TWith2Sugars
    TWith2Sugars over 15 years
    Pablo Marambio - any alterative ways I could perform this?
  • TWith2Sugars
    TWith2Sugars over 15 years
    If I remeber correctly convert.ToIt32 could throw an exception
  • ethan
    ethan over 15 years
  • TheSoftwareJedi
    TheSoftwareJedi over 15 years
    If I didn't want you to use the code, I wouldn't have posted it! :)
  • Judah Gabriel Himango
    Judah Gabriel Himango over 15 years
    +1 for use of the little-known .NET 4.0 design-by-contract APIs.
  • Judah Gabriel Himango
    Judah Gabriel Himango over 15 years
    +1. I don't know why .NET BCL doesn't have a .ForEach extension for IEnumerable<T>
  • abbot
    abbot over 15 years
    Wow, I've been writing methods to map strings to enums (just started using .NET). Thanks, this will absolutely help!
  • Neil
    Neil over 15 years
    You might also consider naming this ToEnum<>(), since it comes after the object.
  • David
    David over 15 years
    Console.WriteLine already has an overload which formats. Console.WriteLine("{0} {1}", value1, value2)
  • Meydjer Luzzoli
    Meydjer Luzzoli over 15 years
    Um, what's with the crazy Substring action though? If you're trying to get rid of the BOM there are much better ways of doing it (such as specifying that it is omitted from the encoding).
  • Rinat Abdullin
    Rinat Abdullin over 15 years
    Problems with these extensions: * All objects are extended (signature pollution) * boxing/unboxing overhead * not all enums derive from int, there could be byte and long as well
  • Adam Lassek
    Adam Lassek over 15 years
    Thanks Rinat, I have actually got this down to a single generic method - see stackoverflow.com/questions/303287
  • sina
    sina over 15 years
    Use dt.ToString("yyy-MM-dd_HH.mm.ss"); directly to avoid creating 2 additional String instances. Since this format doesn't include a time zone component, a UTC time would be better via dt.ToUniversalTime().ToString(...).
  • Jay Bazuzi
    Jay Bazuzi over 15 years
    I'd be tempted to call the first one ToXml() (like ToString())
  • Jonathan C Dickinson
    Jonathan C Dickinson over 15 years
    Oooh, you are going to get a nasty memory leak there. Make sure you have a private Dictionary<Type, XmlSerializer> and cache them in there. The reason for this is because every time you create a serializer .Net loads a new assembly into your appdomain.
  • Jonathan C Dickinson
    Jonathan C Dickinson over 15 years
    I put this up somewhere else on SO, but someone shot it down. Has something to do with that it terminates the expression (i.e. does not return IEnumerable<T>).
  • Rasmus Faber
    Rasmus Faber over 15 years
    Two different files on different drives might coincidentally have the same FileIndex. You need to compare VolumeSerialNumber also - but then your example will fail, since VolumeSerialNumbers are different.
  • Rasmus Faber
    Rasmus Faber over 15 years
  • Portman
    Portman over 15 years
    Apologies to the OP if he intentionally wrote it this way, but the use of MemoryStreams AND XmlReader/XmlWriter was overkill. The StringReader and StringWriter class are perfect for this operation.
  • Alex Baranosky
    Alex Baranosky over 15 years
    I like the name "FormatBy"... it is a little shorter than "FormatWith"
  • chakrit
    chakrit over 15 years
    FileInfo and DirectoryInfo is rather slow compared to their string File and Directory counterpart. You might want to profile those.
  • TWith2Sugars
    TWith2Sugars over 15 years
    Not a problem!, I'll use this altered version myself, thanks.
  • TWith2Sugars
    TWith2Sugars over 15 years
    Just thinking... would it be worth it if we used the "as" keyword and just returned the result as opposed to casting and and catching an exception?
  • TWith2Sugars
    TWith2Sugars over 15 years
    @Jonathan C Dickinson Thanks for the warning!
  • WestDiscGolf
    WestDiscGolf over 15 years
    For string formatting performance and madness you may want to check out Phil Haack's blog about different ways of doing it ... haacked.com/archive/2009/01/14/named-formats-redux.aspx
  • Dan Nelson
    Dan Nelson over 15 years
    What about use an Enum in the parameter instead of plain string
  • MarkJ
    MarkJ over 15 years
    It's an extension method, of course it's going to be unreadable to new members of the team. I thought that was the idea with this witty stuff? How else will the new members know how clever we are?
  • klkitchens
    klkitchens over 15 years
    Ok... I just went to put this into action and went with .With -- so you get "This is a {0}".With("test") and it's very readable and makes sense. FYI
  • Anton Tykhyy
    Anton Tykhyy about 15 years
    Better use TryGetValue, you're doing two lookups instead of just one.
  • JoshBerke
    JoshBerke about 15 years
    x.ThrowIfNull seems wrong to me. Your calling a method on what appears to be an instance member checking if its null. I know this will work since extension methods are just static methods, Its just not intuitive.
  • flq
    flq about 15 years
    Isn't it somewhat dangerous to already enumerate "enumerable" by calling "Count" on it in a contract check? Or is this not a runtime check?
  • Joel Mueller
    Joel Mueller about 15 years
    You still have to put a variable name in front of every method/property call. Why not just make your original variable name shorter?
  • chakrit
    chakrit about 15 years
    @Joel Muller it's not always my variable... think Someone.Else.Namespace.With.WeirdClass.Instance
  • Admin
    Admin about 15 years
    Would be better as this IList<T>
  • fretje
    fretje about 15 years
    Wouldn't the name "IsBetween" make more sense? Also maybe make an IsBetweenInclusive and IsBetweenExclusive. No idea which one to take for default though.
  • Lazy
    Lazy about 15 years
    Why not return the values using yield return and return "actual lazy" enumerators? Would to certain extent take care of your high-performance code comment.
  • Sensei
    Sensei about 15 years
    Beware, this is not threadsafe. You should definitely synchronize your access to the static serialisers dictionary.
  • TWith2Sugars
    TWith2Sugars about 15 years
    @Yann Schwartz How would I start with that?
  • Neil
    Neil about 15 years
    Post on why LINQ's IEnumerable<T> extensions don't include a ForEach: stackoverflow.com/questions/317874/…
  • Joel Coehoorn
    Joel Coehoorn about 15 years
    @Steve: it makes more sense if it were a datetime extension.
  • jonny
    jonny almost 15 years
    requires .NET 3.5, uses delegates to evaluate object graph in try catch stackoverflow.com/questions/298009/…
  • Steve
    Steve almost 15 years
    I also use the c# 3.0 property initializer syntax wherever possible to achieve the same result.
  • Steve
    Steve almost 15 years
    @chakrit, here's an example. It only applies when creating the object Button n = new Button { Name = "Button1", Width = 100, Height = 20, Enabled = true };
  • Alex Baranosky
    Alex Baranosky almost 15 years
    To me between implies: 5.Between(5,10) returns false, and 10.Between(5,10) returns false as well. That just feels natural to me.
  • Pop Catalin
    Pop Catalin almost 15 years
    Very usefull method, but I don't think it should be and extension method.
  • MordechayS
    MordechayS almost 15 years
    If you're writing a text editor it probably warrants an extension method, but I agree most of the time it's probably no more than a static private method
  • Greg
    Greg over 14 years
    I like, except I wouldn't say Is or As because doing so implies type comparison/conversion. This is really a parsing method.
  • sisve
    sisve over 14 years
    Adding " ..." would return ShortenToLength + 4 chars, ie a string longer than what the documentation says.
  • Arnis Lapsa
    Arnis Lapsa over 14 years
    Just use collection initializer => var list = new List<int>{5,4,8,4,2};
  • Arnis Lapsa
    Arnis Lapsa over 14 years
    Made this too. One of the rare things i miss from Visual Foxpro. :)
  • Arnis Lapsa
    Arnis Lapsa over 14 years
    Finally something unseen. I like it. :)
  • Arnis Lapsa
    Arnis Lapsa over 14 years
    Check out MvcContrib.FluentHtml
  • andleer
    andleer over 14 years
    You could go with ParseIsInt32(), ParseToInt32 and ParseAsInt32()
  • cbp
    cbp over 14 years
    Good points, Rinat. I wish there was a way to write these extension methods.
  • Frank Krueger
    Frank Krueger over 14 years
    @Yann, @T, It's much easier if you just add the "thread static" attribute. Then a new cache will be created per thread. No need for synchronization.
  • Dan Diplo
    Dan Diplo over 14 years
    Note that Enum.TryParse<T> has been added to Net 4.0 - blogs.msdn.com/bclteam
  • Dan Diplo
    Dan Diplo over 14 years
    Would this be better? public static bool IsNull<T>(this T obj) where T : class { return (obj == null); }
  • marijne
    marijne over 14 years
    Shouldn't you be closing those file handles?
  • Ryu
    Ryu over 14 years
    This code doesn't compile. Array's don't have Contains method
  • Ryu
    Ryu over 14 years
    Well it compiles if you're using System.Linq;
  • Thomas Levesque
    Thomas Levesque over 14 years
    The Aggregate in Capitalize is pretty bad for performance, because it creates many string instances. Why not use word.Substring(1) instead ?
  • Thomas Levesque
    Thomas Levesque over 14 years
    No example ? It's pretty straightforward, but maybe not for everyone
  • Christian.K
    Christian.K over 14 years
    You should at least change that "catch" clause to only catch those exceptions that ChangeType() will raise when it cannot "convert" the reference. I think you wouldn't want to have any OutOfMemoryException, ExecutionEngineException, ThreadAbortException, or alike being treated as a conversion error. Those things will otherwise be pretty hard to track errors.
  • P Daddy
    P Daddy over 14 years
    It would be more .NETy if you used IComparer<T> or Comparison<T> (or an overload for each), instead of a "less" function, which smacks of STL.
  • RCIX
    RCIX over 14 years
    As i understand it a Comparison<T> is basically a Func<T,T,int> in disguise, where i need a bool to work with the insertion sort.
  • P Daddy
    P Daddy over 14 years
    Yes, Comparison<T> is equivalent to Func<T, T, int>, which is the same interface as IComparer<T>.Compare. This is the standard comparer interface that .NET developers are used to. Most sorting functions only need to compare less than or greater than. You've chosen less than. If you look in Reflector at Array.SorterGenericArray.QuickSort() (or Array.SorterObjectArray.QuickSort()), you'll see that Array.Sort also only uses less than, but it does it with comparer.Compare(a, b) < 0, keeping with the established interface for the platform.
  • P Daddy
    P Daddy over 14 years
    Accepting IComparer<T> also allows your users (or you) to use Comparer<T>.Default instead of implementing the comparison by hand. The best interface when a comparison is involved usually has three overloads, one taking IComparer<T>, one taking Comparison<T>, and one taking no comparer and assuming Comparer<T>.Default.
  • Tommy Carlier
    Tommy Carlier over 14 years
    If you use the ArgumentNullException-constructor with only 1 string-argument, that argument has to be just the parameter name, and not the error message. So your code should look like this: if (obj == null) throw new ArgumentNullException(parameterName);
  • David Miani
    David Miani over 14 years
    It seems to me that multiple people have different ideas as to what is natural. Because of this it probably should be explicitly stated what is being used (ie Inclusive vs Exclusive), as this could be a very easy source of errors.
  • darkAsPitch
    darkAsPitch over 14 years
    this mimicks pythons random.choice(seq) function. nice.
  • andriy
    andriy over 14 years
    DateTime.Now.First will be clear enough in Intellisense if the method is well-documented.
  • ICR
    ICR over 14 years
    Your IsNullOrTrimEmpty helper is in .NET 4.0 in the form of string.IsEmptyOrWhiteSpace
  • ICR
    ICR over 14 years
    The BCL guys, but yes, hi 5 indeed.
  • moomi
    moomi over 14 years
    Use as you will for CodePlex or lining your bird cage.
  • jpbochi
    jpbochi over 14 years
    I recommend reading this before using method: blogs.msdn.com/ericlippert/archive/2009/05/18/…
  • jpbochi
    jpbochi over 14 years
    Can someone be kind enough to explain it to the less gifted of us?
  • jpbochi
    jpbochi over 14 years
    You can substitute all the code in this function for one line: return string.Join(separator, list.ToArray());
  • jpbochi
    jpbochi over 14 years
    Beware that argument validation should not reside in the same method as the yield return 's. The problem is that the ArgumentNullException 's will be thrown at the start of iteration of the returned "query". It should have been thrown at the call to the Zip method.
  • jpbochi
    jpbochi over 14 years
    +1 I particularly liked the Pipe method. I had to download your source to find out that it was like a Where on a single value, though. Could someone edit the answer to make this point clearer?
  • jpbochi
    jpbochi over 14 years
    I would rather use as T instead of casting
  • jpbochi
    jpbochi over 14 years
    @Dan Diplo I don't think your change would make any difference at all. It make no difference to use generics to compare an object to null.
  • Kaveh Shahbazian
    Kaveh Shahbazian over 14 years
    'Pipe' is different than 'Where'. 'Where' is a 'map' (in mathematical sense and in functional languages) which takes a set (collection & in .NET case an IEnumerable<T>) & a function (which in .NET land is a delegate and can be represented by a lambda expression like x => x > 2; the only restriction on provided predicate is that it must return a Boolean. 'Pipe' operator is a common tool in functional languages. It's main usage is for chaining computations (function calls). It gets a value & a function (like x => f(x)); then it applies the function to the value & returns the result.
  • Tom Bushell
    Tom Bushell over 14 years
    Maybe "EqualsAnyOf" would be a better name than "In"?
  • Winston Smith
    Winston Smith over 14 years
    I'm not sure I like it - I like the brevity of In, but maybe IsIn would be better.
  • Ian
    Ian over 14 years
    I'm afraid some of these I don't like. 500.Sleep() for example... Just a little too cryptic for my liking. I don't see what's wrong with plain Thread.Sleep()
  • Ray Burns
    Ray Burns over 14 years
    The advantage of using generics is this: If you try to call Dan Diplo's generic version of IsNull() on a struct you get a compile-time error. If you call John Kraft's original version it doesn't warn you (and also adds boxing code).
  • John Kraft
    John Kraft over 14 years
    @Ray Burns You are absolutely correct, however, I consider that to be a plus on mine; it won't throw an exception, and the boxing is the preferred behavior in the code that I am writing. Besides, in the current environment I work in (CRUD line-of-business apps), we never have a need for structs; so it doesn't matter.
  • Max Toro
    Max Toro over 14 years
    Using the same Contains method: (new[] { 1, 2, 3 }).Contains(a)
  • Thomas Levesque
    Thomas Levesque over 14 years
    I think it could be a good idea, but it's hard to implement... You can easily check whether x is null, but if you want to perform the check for every level of the "path" (SomeProperty, MaybeAMethod), it gets really hard. I tried to do it by rewriting the expression tree, but I eventually gave up...
  • Joel Mueller
    Joel Mueller over 14 years
    I called my version of this ToDelimitedString to avoid confusion with the built-in LINQ Join method.
  • Joel Mueller
    Joel Mueller over 14 years
    Looks a lot like System.Data.DataSetExtensions.dll that comes with .NET 3.5, except not as efficient.
  • Dan Tao
    Dan Tao over 14 years
    If your intention is for this method to be used within LINQ queries, then you might want to consider implementing a ShuffledEnumerable class that only does this work (and probably caches it) on GetEnumerator to provide lazy evaluation a.k.a. deferred execution. Otherwise if someone calls, e.g., var shuffledNames = myObjects.Select(x => x.Name).Distinct().Shuffle(); the operation will get executed immediately, which may not be what he/she expects. Good answer, though!
  • Rauhotz
    Rauhotz over 14 years
    Why not just calling List<T>.AddRange(IEnumerable<T> collection) within your method?
  • Dan Tao
    Dan Tao over 14 years
    Couple things: I'd recommend that OneOf should accept any IList<T>. Then you could always also have an overload that takes a params arg and just passes that into the IList<T> overload. I gave an answer (way down at the bottom right now) with a NextBool method similar to your CoinToss, but with an overload that takes a probability parameter (what if I want something to happen 75% of the time?). Also, just a nit pick: your example code will throw a NullReferenceException since rand is never initialized.
  • Dan Tao
    Dan Tao over 14 years
    @Will: Actually, it would be best to accept an ICollection<T>; then it could also be used on, for example, LinkedList<T> and HashSet<T>, not just indexed collections.
  • Dan Tao
    Dan Tao over 14 years
    I believe ToOrNull has the exact same behavior as ToOrDefault (i.e., if you call ToOrDefault on a reference type with an unsuccessful conversion, it will return null). But more importantly, it seems kind of redundant to me since var s = myObject as string accomplishes the same thing as var s = myObject.ToOrNull<string>() -- but without potentially having to catch an InvalidCastException. Am I missing something?
  • jpbochi
    jpbochi over 14 years
    @Dan: This is a great point. There's an elegant way to use deferred execution without an explicit declared class, though. yield return solves the problem. I'll edit my answer.
  • Dan Tao
    Dan Tao over 14 years
    Solid. Now it's basically the logical opposite of OrderBy. Nicely done!
  • Aran Mulholland
    Aran Mulholland about 14 years
    @Arnis L this lets you ADD items to an already existing List<T> and can be called multiple times.
  • John Leidegren
    John Leidegren about 14 years
    If you wanna do that with enumerations change the type object to just Enum.
  • John
    John about 14 years
    Very nice, could be expanded to first check Query string, then check ViewData, then check SessionState, finally return default value.
  • Joel Coehoorn
    Joel Coehoorn about 14 years
    I'd use default(T) for this and remove the class requirement.
  • Joel Coehoorn
    Joel Coehoorn about 14 years
    I'd rename this to AppendRange() - it makes the difference between this and a collection initializer more obvious.
  • Joel Coehoorn
    Joel Coehoorn about 14 years
    It's still dangerous because some enumerables can only be iterated once, but I fixed it so that at least it stops after two iterations rather than determining the entire count.
  • Joel Coehoorn
    Joel Coehoorn about 14 years
    I'd rename these to Append() (and use iterator blocks as suggested by peSHlr)
  • Anthony
    Anthony about 14 years
    Joel, peSHIr: good suggestions, I have updated the answer to do this.
  • adrianm
    adrianm about 14 years
    wouldn't ´builder.AppendFormat(format, args); builder.AppendLine();´ be more in the spirit of the stringbuilder (i.e. no temporary string)
  • MordechayS
    MordechayS about 14 years
    @adrianm isn't that 1 extra string though (albeit just a \n)?
  • adrianm
    adrianm about 14 years
    AppendLine uses a static "\r\n" string. string.Format creates a new string every time which need to be GC:d.
  • stevehipwell
    stevehipwell about 14 years
    Why are you looping the values when you can call list.AddRange(values);?
  • stevehipwell
    stevehipwell about 14 years
    All of these methods appear to be un-needed as you can use the as keyword to get a value from a reader allowing for null. If you combine the null coalescing ?? operator with the as operator you can even have a non-null default value for going directly to a value type. See stackoverflow.com/questions/746767/…
  • stephbu
    stephbu about 14 years
    This seems a a little flawed in assuming FQDN structure - try these test cases. www.msn.co.uk vs. www.msn.com vs. msn.co.uk co definitely isn't the root domain for msn.co.uk.
  • Adam Lassek
    Adam Lassek about 14 years
    @Stevo No, you can't use as in this way. Did you test this? DBNull values will throw an exception.
  • stevehipwell
    stevehipwell about 14 years
    @Adam Lassek - Actually yes I have tested this and have it running in a production environment. I have no idea where you got the impression that an exception would be thrown if a value is DBNull, it really wont; that is data access 101.
  • BlueRaja - Danny Pflughoeft
    BlueRaja - Danny Pflughoeft about 14 years
    Edited to allow covariance in pre-.net 4.0
  • JP.
    JP. about 14 years
    Jon, your site says that this is "licensed under the Apache licence...". Which license is correct: MIT/Apache? Thanks
  • Joel Coehoorn
    Joel Coehoorn about 14 years
    There's a separate keys collection property in the dictionary that might be able to do this faster
  • Ken
    Ken about 14 years
    Python and Common Lisp both use inclusive on the low end, and exclusive on the high end, as in the code above. Yes, it seems "unnatural" at first, but in the first 5 minutes it becomes tremendously useful -- I would classify it as a miswart. After all, every single character in the above code (except possibly <) seemed "unnatural" to me, at first, too -- writing public static class ComparableExtensions { before my code doesn't exactly seem intuitive.
  • johnc
    johnc about 14 years
    Surely if it is null, the call will fail (I once tried to implement an IsNullOrEmpty method on a string and felt foolish when I realised), but it would work well for value types
  • Jim Schubert
    Jim Schubert about 14 years
    A much faster way to get a delimited string is string.Join(",", strings); where strings is an array. This generates roughly 1/3 the IL as the StringBuilder method.
  • Daniel
    Daniel about 14 years
    Nullable tpyes have a HasValue property built into them.
  • John Leidegren
    John Leidegren about 14 years
    @Jim Schubert: Can you back that up with some benchmarks? The size of the IL isn't a good measurement of speed. Fewer instructions doesn't automatically imply faster running times.
  • cbp
    cbp about 14 years
    Just point out that this is still a useful method to have for StringBuilder. If you wanted to seperate the calls to the joining method with other code, then you would have multiple calls to string.Join anyway which would negate any performance benefit over using a StringBuilder.
  • Kamarey
    Kamarey about 14 years
    And what purpose of all these? Why not just write, say, "item as Type" instead of "item.As<Type>()" as you do?
  • Jim Schubert
    Jim Schubert about 14 years
    @John: Benchmarks have been done on these thousands of times, and they rarely, if ever, show any perceptible performance difference. I'd like to do benchmarks on this to see the difference, and compare string.Join/Format/Concat, StringBuilder.Append/AppendFormat, and + operator concatenation. A 300ms difference in building a string can easily be offset by network and database performance, though.
  • johnc
    johnc about 14 years
    @Kamarey It is a subjective preference, but it reduces confusing parens that can build up when you have multiple casts. item as Type becomes (item as Type) or ((Type)item) if you need to use item as the cast type. Also, the left to right scanning of item.As<Type>(). ... is much more readable over boxing in some confusing cases. I did say it was simple, and I agree it is subjective, but I find it can be quite powerful in code readability.
  • John
    John about 14 years
    I made a similar method but I also added an overload which takes BetweenType enum to specify how the compare should take place. sometimes you want a true between (exclusive) sometimes inclusive and sometimes to include one or the other bounds.
  • John
    John about 14 years
    I have a similar method called Parse<T> that I use for all sorts of types, not just int32
  • Iain Galloway
    Iain Galloway almost 14 years
    Doesn't String already implement IEnumerable<char>? So you'd just need to do return new String(input.Reverse());
  • Lazy
    Lazy almost 14 years
    ToPluralString() is just plain simplistic. English is not my native language so it seems silly to me, but it does not even work very well in English in general. ;-)
  • Joe White
    Joe White almost 14 years
    Delphi avoids the confusion of "between" by calling their function "InRange", and returning true at the endpoints. I find this is a more helpful name than the ambiguous "between".
  • Omar
    Omar almost 14 years
    @Simon - Fixed the documentation. @peSHIr - I edited it, could you elaborate please.
  • Gabe
    Gabe almost 14 years
    This would be useful for when you have a lot of events to hook up, because C#'s property initializer syntax doesn't support events.
  • Pure.Krome
    Pure.Krome almost 14 years
    @peSHIr : care to give an example? basically, for a large number (lets keep this simplistic and say 'the majority') of 'things' that are either 0 or 2+ .. end with an s to define that they are plural (or none for 0). eg. cat/cats. dog/dogs. friend/friends. bug/bugs. Now, this won't work for things like fairy/fairies (and all other words that end in y) or tooth/teeth .. etc. So it's a helper ... but not the be-all-end-all of a singlular-to-plural modifications.
  • Lazy
    Lazy almost 14 years
    @Pure.Krome: You already give examples yourself. ;-) Some more: index/indices, saldo/saldi and other Latin based ones. If this is just a helper for use in ToReadableTime() - where it would work great, even if that is not globalized in any way, but the function is not used (?) - I would have expected ToPluralString() to be private instead of public.
  • KdgDev
    KdgDev almost 14 years
    Visual Studio error: Error 2 'System.Array' does not contain a definition for 'Contains' and no extension method 'Contains' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)
  • KdgDev
    KdgDev almost 14 years
    Problem: this requires than 1 parameter. In which case, best to just use the LINQ contains method, right?
  • KdgDev
    KdgDev almost 14 years
    Won't compile, problem with the S and T.
  • Greg D
    Greg D almost 14 years
    I don't really like this one. The where is already performing the if, that's the whole point of the predicate.
  • Casebash
    Casebash almost 14 years
    This should be a separate question
  • brickner
    brickner almost 14 years
    How about using IEnumerable instead of ICollection and Any() instead of Count?
  • Tadas Šukys
    Tadas Šukys almost 14 years
    @brickner IEnumerable<T>.Any() - only generic IEnumerable<T> has Any().
  • Brady Moritz
    Brady Moritz almost 14 years
    @Steve, Im thinking this is provider-dependent.. Ive had oracle providers blow up on DBNull balues, but some others didnt. Been too long though, I'm probably wrong ;)
  • Brady Moritz
    Brady Moritz almost 14 years
    I recommend seeing if can do this for strongly typed datatables? they also dont allow nullable types, and are a huge pain to work with. In fact they are much worse, because if you try to access a field that has a null, the access itself throws an exception.. it doenst even return a dbnull you can inspect.
  • Brady Moritz
    Brady Moritz almost 14 years
    this is also userful outside of property initializers, because you can only use them when creating a new object. this extension can work on previously created objects.
  • andleer
    andleer almost 14 years
    Part of the idea here is that some conditionals won't execute on SQL with an IQueryable so you have to separate them.
  • NickAldwin
    NickAldwin almost 14 years
    And the reverse is already included with .NET as a built-in extension method (yeah, that sounds weird, built-in extension method): stackoverflow.com/questions/208532/…
  • BenAlabaster
    BenAlabaster almost 14 years
    I'd probably just add an overload with a third param to make it more readable and provide a companion enum Match.Inclusive, Match.Exclusive. Default the third param to make it inclusive, but the overload allows that to be explicitly specified: 5.Between(1, 5); returns true, but 5.Between(1, 5, Match.Exclusive); returns false.
  • JBRWilkinson
    JBRWilkinson almost 14 years
    Whoah, Pokemon exception handling is gonna hide issues like ThreadAbortException, etc. Please catch something specific.
  • BuddyJoe
    BuddyJoe almost 14 years
    I would probably write two extension methods - IsInOne() and IsInAll()
  • torial
    torial almost 14 years
    That reminds me of the Python PEP 313, which was an April Fools joke to include Roman Numeral literals in python: python.org/dev/peps/pep-0313
  • Thomas Levesque
    Thomas Levesque almost 14 years
    Wow, 8 parameters (not counting the this parameter) ! IMHO, any method with more than 4 parameters needs refactoring...
  • Thomas Levesque
    Thomas Levesque almost 14 years
    I eventually managed to make it work: tomlev2.wordpress.com/2010/02/21/…
  • Thomas Levesque
    Thomas Levesque almost 14 years
    @johnc, no the call will not fail if o is null. Extension methods are actually static methods, not instance methods. And the IsNullOrEmpty extension method works fine for me...
  • Thomas Levesque
    Thomas Levesque almost 14 years
    You forgot TrueFalseFileNotFound :P
  • Thomas Levesque
    Thomas Levesque almost 14 years
    If you need case insensitive keys, you can pass StringComparer.InvariantIgnoreCase to the dictionary constructor
  • si618
    si618 almost 14 years
    @Thomas - Even better! Assumes you have access to the ctor, but definitely the best approach.
  • EightyOne Unite
    EightyOne Unite almost 14 years
    nice. Just what I'm looking for :-)
  • Fredy Treboux
    Fredy Treboux almost 14 years
    Hey, that's great!. I actually gave it a try a couple of days ago and came up with this: bit.ly/9777Y0 but your approach seems much cleaner. I agree with your conclusions though.
  • StriplingWarrior
    StriplingWarrior almost 14 years
    @Joel: Non-default values for native types are legitimate arguments more often than null values. Checking against null makes more sense to me than checking against default. Of course, I just generalize the whole idea by saying Require.ThatArgument(input != null) or Require.ThatArgument(personId > 0). It doesn't take that much more code, it's a lot more flexible, and it reads nicely. I have additional overrides that take funcs for when you want to customize the error message or the exception itself.
  • StriplingWarrior
    StriplingWarrior almost 14 years
    I don't have to add a bunch of hard-coded values to a list nearly as often as I need to append values to an IEnumerable generally. When I need to do something like this, I just say items = items.Concat(new[] {5, 4, 8, 4, 2}). It works with any IEnumerable (for both the subject and the argument), and if you really want to end up with a list, just call ToList() when you're done.
  • slolife
    slolife almost 14 years
    @Jonathan C Dickinson: It appears from the MSDN docs here msdn.microsoft.com/en-us/library/… that the constructor that is used (new XmlSerializer(type)) does not have a memory leak problem. So maybe the caching code isn't needed?
  • Mark Hurd
    Mark Hurd almost 14 years
    This probably should be duplicated with Literal instead.
  • Greg D
    Greg D almost 14 years
    I've written basically identical code myself on more than one occasion.
  • fre0n
    fre0n almost 14 years
    Interesting. But not exactly extension methods.
  • Lasse Espeholt
    Lasse Espeholt over 13 years
    19.June(1976) is fine (testing at least) but I don't like 30.Minutes(). Why not use operator overloading to reach something more equivalent to scientific notations like 30 * min or 30 * Minutes if you like.
  • Jon Skeet
    Jon Skeet over 13 years
    @lasseespeholt: Well, in both cases you'd have to have min and Minutes defined somewhere in each source file that uses them... and that could get annoying. With the extension method it's just a case of adding the using directive (which we don't tend to look at anyway). But it's definitely a matter of taste.
  • Lasse Espeholt
    Lasse Espeholt over 13 years
    +1 I really like this, but I prefer CoinToss to be implemented with rng.NextDouble() < .5 because internally .Next(int) is made with .NextDouble() so you would save a cast, a * and a check.
  • Lasse Espeholt
    Lasse Espeholt over 13 years
    @Jon Ahh good point ;) of cause it could be static so you could do something like 30 * SI.min but that just make it less clear.
  • Thomas Levesque
    Thomas Levesque over 13 years
    Very similar in purpose to the method I posted here. Your implementation allows more flexible patterns, but mine is probably faster ;)
  • Thomas Levesque
    Thomas Levesque over 13 years
    What if I want thingy.NullOr(t => t.Count), where Count is an int ? You should return default(TReturn) rather than null, that way you won't need the class constraint and it will work for value types too
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    TIn should be required to be a class, otherwise this entire extension method makes no sense (value types cannot be null). And your example with t.Count does work with the above extension method. Could you take a second look?
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    @Kamarey some people call this "fluent" programming - always programming left to right, never having to back up to put parens on things. Reaching for the arrow keys slows things down. It also keeps in style well with Enumerable and Observable operators. @johnc I would add a To<T> to the list that does (T)item.
  • Jim Schubert
    Jim Schubert over 13 years
    @Scott: this is a useful method to a common problem. However, I believe TReturn elseValue = default(TReturn) is only available to .NET 4.0? I have 3.5 SP1 and I've never seen that construct (neither has my compiler). I just moved this to inside the method. One issue, however, is that boxing a nullable type to object for use with the method yields an unexpected result (0 vs expected null).
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    @Jim: the default(T) keyword has been there since VS2005, but I think default parameters is a new .NET 4 feature. The easy way around it should be to have two variants, one that takes the param and one that does not. I'll update the answer to be CLR 2.0 compatible. Regarding the boxing - that's the point of default. It will be 0-initialized data for a value type, and null for all reference types. A TReturn of a value type should remain unboxed all the way through the function.
  • Jim Schubert
    Jim Schubert over 13 years
    @Scott: My question was about the default parameter, which I've only seen in dynamic languages like Ruby. My point regarding nullable types is that returning x.Value should return null (if, for example, int? was null) or the value if int? has a value. Returning 0 when int? x = null is passed and boxed to object is an odd case. I've seen similar checks for nullable types in libraries such as fluent nhibernate and linfu (I think) for this specific case, allowing you to drop the class constraint as previously suggested.
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    @Jim I believe the default param like that is also possible in C++. I don't know why it would only be common in a dynamic language, because it is a statically typed feature (template params are known at compile time). Regarding int?, the class constraint is required or the function won't compile. You cannot compare to null without requiring a reference type. Now, it is possible to have a second version of the function that takes TIn? But what should it do? Return a null or the boxed Value? But we already have that in the form of the nullable.. I don't see the added value...
  • Jim Schubert
    Jim Schubert over 13 years
    @Scott: Thanks for mentioning the default parameters in C++. I have seen them in C++, but that was in school and I had long since forgotten about them. In Ruby, they're called "optional parameters" instead of "default parameters" and I associated them with dynamic languages because they force the type of the parameter. In Ruby's case, the variable's type can't be changed but the variable can be reassigned. I have heard about default parameters in VB.NET under 3.5 and it's enough for me to upgrade to 4.0. You're right, though, about there being little added value for nullables.
  • Jim Schubert
    Jim Schubert over 13 years
    ... I just thought the side effects of boxing a struct were worth mentioning.
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    As mentioned, this is for WinForms only. It may work with WPF but there are issues (described in the comment about WPF at msdn.microsoft.com/en-us/library/…). The best solution for WPF I've found is described in geekswithblogs.net/lbugnion/archive/2009/09/05/… (though, as it's a static property, it does not really work as an extension method.)
  • CodesInChaos
    CodesInChaos over 13 years
    Be careful when using it with float or double. The semantics of those differ between IComparer and the < = > operators for infinities and NaNs. That 0 is signed (there are distinct +0 and -0) might create problems too.
  • CodesInChaos
    CodesInChaos over 13 years
    I don't think this method should use Trim. Trimming the input should be the responsibility of the caller.
  • CodesInChaos
    CodesInChaos over 13 years
    An implementation using StringBuilder should be faster.
  • Jürgen Steinblock
    Jürgen Steinblock over 13 years
    Could be extende to be more generic, too public static bool CompareByProperty<Tself, Tother>(this Tself self, Tother other, string propertyName) but you will have to change the comparison to use Equals(value1, value2) instead of == since == compares the reference for object types: stackoverflow.com/questions/814878/…
  • Simen Echholt
    Simen Echholt over 13 years
    ((src == null || src.Count == 0) ? true : false) == (src == null || src.Count == 0)
  • jpbochi
    jpbochi over 13 years
    Why not an IsNullOrEmpty<T>() that accepts an IEnumerable<T>?
  • jpbochi
    jpbochi over 13 years
    By the way, you lost my vote up by appending that ? true : false.
  • Greg
    Greg over 13 years
    This should be split into two separate answers. The first one is ok (should be IEnumerable<T> instead of List<T>). The second is dubious. I agree with @SchlaWiener, make it generic. I'd also lose the catch. If an exception is thrown, let the caller decide how to handle it.
  • Michael Stum
    Michael Stum over 13 years
    @CodeInChaos The Benchmarking in stackoverflow.com/questions/228038 measured that StringBuilder is slower.
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    The Reactive Extensions includes IEnumerable<T>.Run() with many overloads. Apparently Erik Meijer's group is at odds with Eric Lippert's group.
  • Davy8
    Davy8 over 13 years
    Not sure what I think of using @this as the parameter name. On the one hand since it's an extension method you can think of it as a regular class method. On the otherhand, using a (common) keyword as a parameter name rubs me the wrong way. Sounds interesting though.
  • CodesInChaos
    CodesInChaos over 13 years
    You're right. It seems like the thread safety requirements (probably to ensure immutability of the string returned by ToString) slow StringBuilder down a lot.
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    I originally picked up @this somewhere on a blog or maybe here on SO. Initially I had the same misgivings, but I've been using it for all my extension methods for the past few weeks and have grown to really like it. I think the "can think of it as a regular class method" outweighs pretty strongly the concern about reusing a keyword. I did think about using "th" or "self" for names, but I especially like how the @ really jumps out. It constantly reminds me what kind of method I'm in.
  • xofz
    xofz over 13 years
    Hey Scott, I don't really have much experience with Tasks or Rx and I'm having a hard time following the implementation of this method. Is this useful for when evaluating individual items in a sequence is expensive (thus warranting async eval)? Does it create a new thread for each item or does it reuse the same job thread as more items are pushed?
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    This is useful for when the sequence is expensive. A single thread is pulled from the pool to walk the enumerable asynchronously. It does not return until the enumerable is completed or an exception is thrown. Technically, none of the dispatcher stuff is necessary for this example.. I included it because I write a lot of WPF code and this is a frequent pattern of mine: send a task go do something, publish it as an observable, dispatching the results through the UI thread's message queue.
  • dalle
    dalle over 13 years
    Hope you don't encounter any surrogates or combining characters.
  • binarydreams
    binarydreams over 13 years
    Any reason why enumerable.ToObservable(Scheduler.TaskPool) doesn't solve the same problem?
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    @Richard - nope! Didn't know about that function. :)
  • Thomas Levesque
    Thomas Levesque over 13 years
    The IsNullOrEmpty method is a good idea, I use it all the time (but with IEnumerable<T>, not List<T>)... but I'm pretty sure it has already been posted. Regarding the second method, I see no reason to restrict it to FileInfo. Also, passing a string with the property name is a bad idea: you can do the same with a delegate, and you avoid the overhead of reflection
  • Can Sahin
    Can Sahin over 13 years
    So, what's wrong with simply writing { var x = someVeryVeryLonggggVariableName; /* do something with x */ }?
  • Thomas Levesque
    Thomas Levesque over 13 years
    There is an issue with this solution: you can only use it if the event is declared in the current class, not if it's declared in a base class...
  • Will Vousden
    Will Vousden over 13 years
    @Thomas: Isn't the same is true for raising events manually? The solution is to use the protected virtual void OnBar(Eventargs e) pattern outlined here: msdn.microsoft.com/en-us/library/hy3sefw3%28VS.80%29.aspx.
  • Thomas Levesque
    Thomas Levesque over 13 years
    Yes, but what I mean is that your solution doesn't work in the general case
  • Greg
    Greg over 13 years
    Generalized to ICollection<T>
  • SLaks
    SLaks over 13 years
    Actually, this is thread-safe in older versions too. I've written identical methods myself.
  • chakrit
    chakrit over 13 years
    @Heinzi You get a new scope (the With block scope) and the ability to inline complex access to the object. Also, it doesn't interrupts your train of thoughts as much since you don't have to backtrack and put it in a variable. See: msdn.microsoft.com/en-us/library/ms172864(VS.80).aspx ...
  • Agent_9191
    Agent_9191 over 13 years
    How is this an advantage over the default OrderBy and OrderByDescending?
  • KeithS
    KeithS over 13 years
    OrderBy() cannot be chained; each call to OrderBy() sorts by a single projection of the collected type. You could still make it work if the sorting algorithm used were stable like MergeSort, but the built-in sorting helper is an unstable QuickSort, so there's no guarantee of maintaining relative order when sorting by equal terms. Chaining OrderBy() would also run an O(nlogn) function once for each OrderBy(); this set of methods sorts once no matter how many terms you compare.
  • abatishchev
    abatishchev over 13 years
    @jpbochi: This is just Microsoft demagogy
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    This could be improved by avoiding the ToArray(). While OrderBy cannot be chained, you should be able to chain all of the Comparers into an IComparer<T> that you pass to a single OrderBy, right?
  • KeithS
    KeithS over 13 years
    Well, sorting (ANY algorithm) requires knowledge of the entire Enumerable, because the very last element could be the one that comes first in the ordered collection. OrderBy(), behind the scenes, basically does what I'm doing here; slurp the source Enumerable into a finite collection, sort it, then yield through it.
  • Esben von Buchwald
    Esben von Buchwald over 13 years
    Point taken. :) Also: how does this set of classes differ from the Enumerable.ThenBy() and IOrderedEnumerable types in the .NET Framework?
  • KeithS
    KeithS over 13 years
    Actually, it doesn't as written. I didn't know about the existence of ThenBy() when I first wrote this. However, there are some advantages. Because it's a roll-your-own, it's more extensible; for instance, you could add OrderUsing() and ThenUsing() methods that allow passing a Comparison instead of just a projection (allowing sorting based on members that aren't IComparable). You can also performance-tune the sorting by replacing Array.Sort with, for example, a parallel MergeSort.
  • John
    John over 13 years
    Thanks Jim. Keep up the constructive comments, very useful.
  • KeithS
    KeithS over 13 years
    We have some similar ones in our codebase: IsBefore(), IsOnOrBefore(), IsOnOrAfter(), IsAfter(), IsBeforeToday(), IsAfterToday(). They wrap rather trivial code, but they improve readability significantly.
  • Jim Schubert
    Jim Schubert over 13 years
    @John: no problem. Here's a few issues: You're generating a private class with public accessors. StringBuilder has an AppendFormat method which uses index formatters just like String.Format. You shouldn't be calling Replace on String template place holders like that anyway. You're implicit-typing string. The only reason to convert a struct.Name to the alias is readability, even then it doesn't make much sense. And, IntPtr is platform-specfic so this code only works on 64-bit. The code generated by this won't reflect the actual code you're trying to generate.
  • Jim Schubert
    Jim Schubert over 13 years
    Also, I apologize for the laconic answer-- I was at work. Here is an excellent chapter from O'Reilly on reflection which I think will help you to better examine the types you're trying to mimic the code for: oreilly.com/catalog/progcsharp/chapter/ch18.html
  • John
    John over 13 years
    Should a private class not have any accessors with more visibility than private? I would rather force the programmer to change the visibility than than to assume public or anything else. I realize there is the appendformat and I use it quite often but I also need the new line and unfortunately we don't have and AppendFormatLine.
  • John
    John over 13 years
    Generally I think you are missing the point entirely. This is not intended to be used as is. More likely it is to be used on a more customized basis. For example, you have a large object you want to represent, either from a DB or a class you don't have access to the source. You run through linqpad to generate the class, make few mods and off you go.
  • John
    John over 13 years
    BTW: It is my opinion that if you don't have enough time to extrapolate on your negative opinion you should keep it to yourself until such time that you do. Thanks again - John
  • Jim Schubert
    Jim Schubert over 13 years
    Should a private class not have any accessors with more visibility than private? No. Unless this class is a nested class, which your code doesn't suggest, you'll get the error Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal. I can understand quickly generating classes to match db, I do it myself. Also, StringBuilder has AppendFormat() and AppendLine(); Just call them both or write an extension method called AppendFormatLine.
  • John
    John over 13 years
    "No. Unless this class is a nested class, which your code doesn't suggest". My code doesn't suggest a thing. It simply generates a class and forces the programmer to decide what the accessibility of the generated class should be. "StringBuilder has AppendFormat() and AppendLine(); Just call them both or write an extension method" That is one way to solve it. I could also use string.Format inside the AppendLine.
  • John
    John over 13 years
    "You're implicit-typing string. The only reason to convert a struct.Name to the alias is readability, even then it doesn't make much sense". Please explain this further. Are you saying I should leave it as "String", as it comes through, instead of "string"? "And, IntPtr is platform-specfic so this code only works on 64-bit". All well and good but the code will work in 32 bit. I'm not using IntPtr anywhere. I'm simply representing it as a long if it comes through. As is the case in the example I provided.
  • Jim Schubert
    Jim Schubert over 13 years
    Implicity-typing string using the var keyword causes the compiler to determine that variable's type. When you know it's a string, why not call it a string so the compiler doesn't have to do anything extra? The comment about the struct.Name getting converted to an alias means you are taking the actual struct from the BCL (e.g. Int32) and renaming it in a string using it's alias (e.g. int). There's nothing really wrong with this, but you can just as easily call an int "Int32" or a long "Int64" or an IntPtr "IntPtr". In changing the name to the alias, you've introduced that 64-bit bug.
  • Jim Schubert
    Jim Schubert over 13 years
    In regards to your comment about class-level accessibility defaulting to private: the default access for a class if you leave off the access modifier is internal. My point is that I don't understand why you're "forcing the developer" to do something by generating code that will not compile... why not leave off the access modifier? Isn't that the convention used when Visual Studio generates a class stub for you? By using the private variable, you're inevitably going to cause confusion.
  • Jim Schubert
    Jim Schubert over 13 years
    Also, if you find yourself using this code pretty frequently, it may be worth it to dish out $125 and by .NET Reflector Pro: red-gate.com/products/reflector Then, you will be able to analyze the exact internals of most .NET libraries. I'm sure you've already heard of it, but others reading this thread may not have.
  • John
    John over 13 years
    My job is not to make the job of the compiler easier. The job of the compiler is to make my life easier. I take advantage of it whenever possible if it makes sense (We use var quite often at work and it has paid off many times). Using var for strings is perfectly fine in my opinion. I could easily leave the types as what they come through but since this is intended to generate a class that the user will then incorporate into their code then it should be written as they would. Do you use "Int32 x = 5" in your code? The IntPtr is not a bug, as I said before, it will work on 32 bit.
  • John
    John over 13 years
    I'm well aware of the benefits of reflector. We use the free version all the time. The pro version doesn't have anything additional that I would find useful. As for the private part, again you are missing the point of the code. I'll just leave it at that since this is going nowhere.
  • jpbochi
    jpbochi over 13 years
    @abatishchev And your comment is just prejudice against Microsoft. It does not invalidade any word written by Eric. Someone's arguments are not made valid or invalid just because of the company he/she works for.
  • jpbochi
    jpbochi over 13 years
    By the way, let me make one point clear. I didn't say you should not use this ForEach extension method. I just said that you should consider the points that Eric exposed before you decide whether to use it or not. I read it and I decided not to use it. You're free to do whatever you want with your code.
  • abatishchev
    abatishchev over 13 years
    @jpbochi: I respect Eric very much. Nevertheless he reads out official Microsoft team's architecture position which I called demagogy
  • csharptest.net
    csharptest.net over 13 years
    +1 - I generally hate extension methods for Null objects; however, this is a really nice usage!
  • chakrit
    chakrit over 13 years
    ReactiveExtensions are made for "Reactive" programming. It, naturally, if you understands "Reactive" programming, requires the "Run()" method. There is nothing at odds between the groups. They are simply offering two different ways to code using two different frameworks.
  • Greg
    Greg over 13 years
    Why do you use method.DynamicInvoke()? A direct call like this: method() is much faster. stackoverflow.com/questions/932699/…
  • Roman A. Taycher
    Roman A. Taycher over 13 years
    The stuff I saw showing how to call a lambda used .DynamicInvoke(), I wasn't sure there was a better way.
  • Roman A. Taycher
    Roman A. Taycher over 13 years
    Was calling DynamicInvoke() the only thing I did wrong or something else too? If it was something else I'm curious what else caused the downvotes. I appreciate the invoke explanation and would be glad to hear anything else I got wrong.
  • Greg
    Greg over 13 years
    I'm not sure why this got a couple downvotes, I don't see anything wrong with the code itself. Maybe the downvoters thought that the methods weren't very C#-ish. You explain that you are borrowing from Smalltalk's style, so I don't see what's wrong with that.
  • Roman A. Taycher
    Roman A. Taycher over 13 years
    I don't expect to use the ifTrue/ifFalse on actual code, it was just fun to implement.
  • Thomas Levesque
    Thomas Levesque over 13 years
    Nice one! Would you know how to do the same with WPF (not using GDI)?
  • dbort
    dbort over 13 years
    You could replace everything in your Join<T> method with this: return string.Join(seperator, self.ToArray()).
  • 19WAS85
    19WAS85 over 13 years
    Oh really, I forgot this method. Thanks, Pondidum! Edited.
  • HuseyinUslu
    HuseyinUslu over 13 years
    It may be, i've not checked all the answers.
  • Jeroen Wiert Pluimers
    Jeroen Wiert Pluimers over 13 years
    All TryXxx have an out parameter and bool result: that is the whole point of that pattern! Your method should be called something like DefaultGetValue to set it apart from TryGetValue.
  • Davy8
    Davy8 over 13 years
    @Jeroen Agreed, although I'd call it GetValueOrDefault to be more in line with other similar methods like FirstOrDefault
  • Shaul Behr
    Shaul Behr over 13 years
    OK, point taken, I've renamed the method as @Davy8 suggested.
  • Jeroen Wiert Pluimers
    Jeroen Wiert Pluimers over 13 years
    @Davy8: excellent suggestion; @Shaul: thanks for fixing it (+1).
  • Nicolas Fall
    Nicolas Fall over 13 years
    @webDevHobo - System.Linq is the required using statement, also that means you have to have either linqBridge.dll or .net 3.5 or higher. Contains - msdn.microsoft.com/en-us/library/bb339118.aspx LinqBridge - code.google.com/p/linqbridge
  • Greg
    Greg over 13 years
    @Jonathan, @Yann, @Frank @slolife, @TWith2Sugars - After reading the MSDN link (msdn.microsoft.com/en-us/library/…) provided by @slolife, I think it is safe to say that we don't have to worry about generating a new assembly on every call (as suggested by @Jonathan). I have removed the superfluous caching and cleaned up the code.
  • Alex Essilfie
    Alex Essilfie about 13 years
    This is a good extension method considering String.Replace does not modify the source string.
  • Thomas Levesque
    Thomas Levesque about 13 years
    How is it different from TakeWhile? (except for the overloads with Action)
  • Pavel Hodek
    Pavel Hodek almost 13 years
    Yes, if someone forgot "Null Object Pattern" this method is useful to patch it. Collection should never be null.
  • Espo
    Espo almost 13 years
    Default should be inclusive. If someone says to you "Pick a number between 1 and 9", both 1 and 9 is possible answers in most situations.
  • kirk.burleson
    kirk.burleson almost 13 years
    I joined a new team about 5 months ago and I see this stupid ".F" method used alot. And of course they refuse to change the name...
  • JBSnorro
    JBSnorro almost 13 years
    I thought of In<T>(...) as well and found it to be the most useful extension method outside of the standard library. But I am at odds with the name In. A method name is supposed to be describing what it does, but In doesn't do so. I've called it IsAnyOf<T>(...), but I guess IsIn<T>(...) would be adequate as well.
  • MikeKulls
    MikeKulls almost 13 years
    This is a little excessive having something so specific available to every string object in your app. Especially when you can just use myString.Any(c => c != '0')
  • MikeKulls
    MikeKulls almost 13 years
    It's not a plus because it will always return false on structs. That means that if someone uses it on a struct it is most likely something they did by mistake but they get no error or warning. Considering Dan's method looks identical when you call it (ie, there is no downside to using it) then there isn't any way you could consider your version a plus.
  • John Kraft
    John Kraft almost 13 years
    I'm confused at the concern over structs. A struct, by definition, can never be null. Therefor, the fact that it returns false on a struct is correct behavior.
  • Thomas Levesque
    Thomas Levesque almost 13 years
    @MikeKulls, actually it should be myString.All(c => c == '0') if you want to keep the same meaning...
  • Thomas Levesque
    Thomas Levesque almost 13 years
    It doesn't have to be specific to persian, you can make it work for any culture (example here). Also, you should use a StringBuilder instead of string concatenation for better performance
  • Thomas Levesque
    Thomas Levesque almost 13 years
    Even if you cache the MethodInfo in a dictionary, calling MethodInfo.Invoke is still very slow... you should create and cache dynamically created delegates instead
  • jpbochi
    jpbochi over 12 years
    Just found a slightly more flexible version here: stackoverflow.com/a/5807238/123897
  • demoncodemonkey
    demoncodemonkey over 12 years
    +1, I use these all the time. I was just about to post an answer with exactly the same code until I found your answer already exists :D
  • zzzzBov
    zzzzBov over 12 years
    Use an enum (neither, lower, upper, both) as a third parameter to specifiy equality on bounds. default to neither.
  • xxbbcc
    xxbbcc over 12 years
    In my opinion this is really poor coding style. Constants should be used instead, not obfuscated logic.
  • leviathanbadger
    leviathanbadger over 12 years
    Or even string newlines of the form "\r\n". Or double newlines of the form "\n\r", for that matter.
  • leviathanbadger
    leviathanbadger over 12 years
    You should remove the foreach loop and replace the body of the if statement with yield return array[k] = array[n];
  • Thomas Levesque
    Thomas Levesque over 12 years
    @aboveyou00, for performance mostly. Also, there's no obvious equivalence between a regex and a wildcard pattern, and a wildcard is easier to use if you don't need the full power of a regex.
  • leviathanbadger
    leviathanbadger over 12 years
    I don't know about calling it Open, but these are still good extensions and I'm surprised that nobody has posted them before.
  • jeremysawesome
    jeremysawesome about 12 years
    The name makes perfect sense, especially if you've used similar functionality in MySQL. dev.mysql.com/doc/refman/5.5/en/…
  • Wolf5370
    Wolf5370 about 12 years
    hahaha Just read the article (Joel's comment above) - funny true, but having been in pretty much the same boat (on the recieving end, not the Paula end) it's only funny looking back! Once had a contractor brought in to work on a project I was designigner/lead dev on - she was not under my direct control, but was assigned work from my teams work list. Bosses lauded her as being brilliant (even hiring her again later as a Dev Lead!). It never dawned on them that every piece of code she wrote or designed had not made it to production and all had to be completely rewritten from scratch by my team!
  • Wolf5370
    Wolf5370 about 12 years
    To include names and nullable value types, I do it like this: public static void ThrowIfNull<T>(this T item, string name) where T : class {if (item == null) throw new ArgumentNullException(name);} public static void ThrowIfNull<T>(this T item) where T : class {if (item == null) throw new ArgumentNullException();} public static void ThrowIfNull<T>(this T? item, string name) where T : struct {if (item == null) throw new ArgumentNullException(name);} public static void ThrowIfNull<T>(this T? item) where T : struct {if (item == null) throw new ArgumentNullException();}