Wilsonhut

Deal with it or don't

Monthly Archives: July 2010

Partition a string

This was started by another guy at work.
We needed to break a string up into fixed-width lines. This does that and returns an IEnumerable containing the lines.

public static IEnumerable<string> Partition(this string toPartition, int size)
{
	if (toPartition == null)
	{
		throw new ArgumentNullException("toPartition");
	}
	if (string.IsNullOrEmpty(toPartition) || size == 0)
	{
		return new []{toPartition};
	}
	if (size < 0)
	{
		throw new ArgumentOutOfRangeException("size", size, "size must be non-negative");
	}
	return toPartition
		.Select((character, index) => new {index, character})
		.GroupBy(p => p.index/size,
		      (x, anons) => anons.Aggregate(new StringBuilder(size), (builder, anon) => builder.Append(anon.character)).ToString());
}
Advertisements

Bring Main Window to Front

No description necessary…

public static bool BringMainWindowToFront(this Process process)
{
	if (process == null)
	{
		throw new ArgumentNullException("process");

	}
	return NativeMethods.SetForegroundWindow(process.MainWindowHandle);
}

internal static class NativeMethods
{
	[DllImport("user32.dll")]
	[return: MarshalAs(UnmanagedType.Bool)]

	internal static extern bool SetForegroundWindow(IntPtr hWnd);
}

Now you can say:

myProcess.BringMainWindowToFront();

SingleOrDefault overload with default

Ever have to write something like this?:

var theOneIWant = someListOfThings.SingleOrDefault(thing => thing.IsMostAwesome) ?? Thing.Empty;

…which is simply abhorrent. You’d rather write something like this:

var theOneIWant = someListOfThings.SingleOrDefault(thing => thing.IsMostAwesome, Thing.Empty);

…SO much better.

Well, your wait is over. Now you can.

public static T SingleOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate, T defaultValue)
{
  return source.SingleOrDefault(predicate, () => defaultValue);
}
 
public static T SingleOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> getDefaultValue)
{
	if (source == null)
		throw new ArgumentNullException("source");
	if (predicate == null)
		throw new ArgumentNullException("predicate");
	var single = default(T);
	int num = 0;
	foreach (var item in source.Where(predicate))
	{
		single = item;
		if (++num > 1)
		{
			break;
		}
	}
	switch (num)
	{
		case 0:
			return getDefaultValue();
		case 1:
			return single;
		default:
			throw new InvalidOperationException("Sequence contains more than one element");
	}
}

Also, if obtaining the default value is expensive, you can use the overload that takes a lambda, so it’s only executed if it’s needed.

Enum GetDescription

So, wilsonhut of the future. You’ve come here to copy/paste this code again…

This one’s a slam dunk. You need a enum to be the values in a combo box or something, and you want the text of each option to be friendly text.

Consider this ridiculous enum:

public enum VanHalenSingers
{
  [Description("[Select]")]
  Undefined,
  [Description("Diamond Dave")]
  DavidLeeRoth,
  [Description("The Red Rocker")]
  SammyHagar,
  [Description("I Think That Is All")]
  TheOtherGuy,
}

Now the code:

public static string GetDescription<T>(this T enumValue)
{
  if(Equals(enumValue, null))
  {
    throw new ArgumentNullException("enumValue");
  }
  if (!(enumValue is Enum))
  {
    throw new ArgumentException("enumValue must be an Enum.");
  }

  var memberInfos = enumValue.GetType().GetMember(enumValue.ToString());

  if (memberInfos != null && memberInfos.Length > 0)
  {
    var attributes = memberInfos[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

    if (attributes != null && attributes.Length > 0)
    {
      return ((DescriptionAttribute)attributes[0]).Description;
    }
  }
  return enumValue.ToString();
}

So you can call it like this:

Console.Write(VanHalenSingers.DavidLeeRoth.GetDescription());

That will output “Diamond Dave”

TakeAllButLast

[UPDATE: Newer TakeAllButLast!]
Linq provides us with the extension method First() to get the first item in an enumerable. It also gives us Take(x) to get the first x items. The provided Last() extension method has no “TakeAllButLast(x)” equivalent.

I wanted one, so I wrote it (with a conceptual tip provided by a coworker). It’s not trivial to do if you want to make sure that you only enumerate the list once.

public static IEnumerable<T> TakeAllButLast<T>(this IEnumerable<T> enumerable, int count)

{

  if (enumerable == null)

  {

    throw new ArgumentNullException(“enumerable”);

  }

  var enumerator = enumerable.GetEnumerator();

  if (count < 0)

  {

    throw new ArgumentException(“Parameter count can’t be negative.”, “count”);

  }

  var segment = enumerator.GetNext(count + 1);

  if (segment.Length <= count)

  {

    yield break;

  }

  for (var i = 0; ; i = (i + 1) % segment.Length)

  {

    yield return segment[i];

    if (!enumerator.MoveNext())

    {

      yield break;

    }

    segment[i] = enumerator.Current;

  }

}

private static T[] GetNext<T>(this IEnumerator<T> enumerator, int count)

{

  return Enumerable.Repeat(true, count)

    .Where(b => enumerator.MoveNext())

    .Select(b => enumerator.Current)

    .ToArray();

}

Notice, there’s also an extension method in there called GetNext on the Enumerator. Crazy!

Sift

So the Except linq Extension method effectively does a Distinct on your list. I wanted it to leave my list alone, other than removing the matching items from the other list, of course.

I called it Sift. Here it is:

public static IEnumerable<T> Sift<T>(this IEnumerable<T> enumerable, IEnumerable<T> other)
{
  var otherList = new HashSet<T>(other);
  return enumerable.Where(item => !otherList.Contains(item));
}

BTW – The HashSet’s Contains method is WAAAY faster than an array’s Contains method.

Here’s an example of how to use it:
Suppose you have string, and you want to create a file using that string as the name, but you want the name to only use acceptable characters…

It’d be nice to have a method on a string that would turn it into a File Name-Friendly string…

 public static string ToFileNameFriendlyString(this string value)
 {
   return new string(value.ToCharArray().Sift(Path.GetInvalidFileNameChars()).ToArray());
 }

Then you would call it like so:

var fileName = "2010/07/12".ToFileNameFriendlyString();

fileName would then contain “20100712”