Какие ваши любимые методы расширения для C #? (Codeplex.com/extensionoverflow)

501

Позвольте составить список ответов, в которых вы публикуете свои отличные и любимые методы расширения .

Требование состоит в том, чтобы полный код должен быть опубликован, а также пример и объяснение того, как его использовать.

Основываясь на высоком интересе к этой теме, я установил проект с открытым исходным кодом с именем extensionoverflow на Codeplex.

Пожалуйста, отметьте свои ответы с принятием, чтобы поместить код в проект Codeplex.

Пожалуйста, напишите полный исходный код, а не ссылку.

Новости Codeplex:

24.08.2010 Страница Codeplex находится здесь: http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize/XmlDeserialize теперь Реализовано и Проверено устройство.

11.11.2008 Есть еще место для большего количества разработчиков.;-) Присоединиться сейчас!

11.11.2008 Третий участник присоединился к ExtensionOverflow, добро пожаловать в BKristensen

11.11.2008 FormatWith теперь Реализовано и Тестирование устройства.

09.11.2008 Второй участник присоединился к ExtensionOverflow. добро пожаловать в chakrit.

09.11.2008 Нам нужно больше разработчиков.; -)

09.11.2008 ThrowIfArgumentIsNull в настоящее время Реализовано и Тестирование устройства на Codeplex.

  • 0
    Теперь первый код размещен на сайте Codeplex.
  • 0
    Эрик, к сожалению, все запущено сейчас на codeplex. Пожалуйста, присоединяйтесь в любом случае.
Показать ещё 2 комментария
Теги:
extension-methods
open-source

149 ответов

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

Позволяет мне заменить:

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....
}

С

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....
}
  • 0
    Сделал это тоже. Одна из редких вещей, которые я скучаю по Visual Foxpro. :)
  • 0
    Этот код не компилируется. У массива нет метода Contains
Показать ещё 11 комментариев
168

У меня есть различные методы расширения в моем проекте MiscUtil (здесь доступен полный источник - я не буду повторять его здесь). Мои избранные, некоторые из которых связаны с другими классами (такими как диапазоны):

Дата и время - в основном для модульных тестов. Не уверен, что я буду использовать их в производстве:)

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

Диапазоны и степпинг - массивный благодаря Марку Гравелю за его операторский материал, чтобы сделать это возможным:

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

Сравнения:

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

Проверка аргументов:

x.ThrowIfNull("x");

LINQ to XML применяется к анонимным типам (или другим типам с соответствующими свойствами):

// <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()

Нажмите LINQ - потребуется слишком много времени для объяснения здесь, но найдите его.

  • 1
    Это мило! Вы должны поставить его на Google Code или CodePlex, чтобы я мог отправить вам несколько исправлений :-) Я обещаю, что он будет читабельным :-P
  • 0
    Да, я переместу его в Google Code некоторое время ... и переименую в то же время, вероятно! (MiscUtil - ужасное имя.)
Показать ещё 13 комментариев
147

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);
    }
}

Пример:

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

Для быстрого копирования и вставки здесь.

Разве вам не кажется более естественным ввести "some string".F("param") вместо string.Format("some string", "param")?

Для более читаемого имени попробуйте одно из этих предложений:

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");

..

  • 11
    Это конечно коротко - но будет нечитаемо любым новым членам вашей команды.
  • 0
    удобочитаемость - единственная причина, по которой я бы не использовал это, кроме того, это хорошая идея
Показать ещё 22 комментария
89

Используются ли они?

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!");
  • 0
    это имитирует функцию питонов random.choice (seq). отлично.
  • 6
    Пара вещей: я бы порекомендовал OneOf принять любой IList<T> . Тогда вы могли бы также всегда иметь перегрузку , которая принимает params ARG и просто передает , что в IList<T> перегрузки. Я дал ответ (прямо внизу прямо сейчас) с помощью метода NextBool похожего на ваш CoinToss , но с перегрузкой, которая принимает параметр probability (что, если я хочу, чтобы что-то происходило в 75% случаев?). Кроме того, просто NullReferenceException : ваш пример кода вызовет NullReferenceException поскольку rand никогда не инициализируется.
Показать ещё 1 комментарий
73
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;
  }
}

Пример:

if (myNumber.Between(3,7))
{
  // ....
}
  • 0
    Это хорошо, я помню, как в моей последней версии 1.1 был написан ряд BetweenInt32, BetweenDateTime и т. Д.
  • 19
    Мне нравится этот, но я пытаюсь решить, правильно ли делать проверку границ включительно по минимальному значению, но исключительно по максимальному значению. Интересно, если это будет сбивать с толку. 5. Между (5,10) верно, но 5. Между (1,5) неверно. Даже не уверен, что метод компаньона внутри поможет. Thougts?
Показать ещё 11 комментариев
58

Метод расширения:

public static void AddRange<T, S>(this ICollection<T> list, params S[] values)
    where S : T
{
    foreach (S value in values)
        list.Add(value);
}

Метод применяется для всех типов и позволяет добавлять диапазон элементов в список в качестве параметров.

Пример:

var list = new List<Int32>();
list.AddRange(5, 4, 8, 4, 2);
  • 15
    Было бы лучше, как этот IList <T>
  • 21
    Просто используйте инициализатор коллекции => var list = new List<int>{5,4,8,4,2};
Показать ещё 9 комментариев
53

Обязательно поместите это в проект codeplex.

Сериализация/десериализация объектов в XML:

/// <summary>Serializes an object of type T in to an xml string</summary>
/// <typeparam name="T">Any class type</typeparam>
/// <param name="obj">Object to serialize</param>
/// <returns>A string that represents Xml, empty otherwise</returns>
public static string XmlSerialize<T>(this T obj) where T : class, new()
{
    if (obj == null) throw new ArgumentNullException("obj");

    var serializer = new XmlSerializer(typeof(T));
    using (var writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

/// <summary>Deserializes an xml string in to an object of Type T</summary>
/// <typeparam name="T">Any class type</typeparam>
/// <param name="xml">Xml as string to deserialize from</param>
/// <returns>A new object of type T is successful, null if failed</returns>
public static T XmlDeserialize<T>(this string xml) where T : class, new()
{
    if (xml == null) throw new ArgumentNullException("xml");

    var serializer = new XmlSerializer(typeof(T));
    using (var reader = new StringReader(xml))
    {
        try { return (T)serializer.Deserialize(reader); }
        catch { return null; } // Could not be deserialized to this type.
    }
}
  • 0
    Я обнаружил, что пишу что-то очень похожее.
  • 0
    Хм, а что за сумасшедший экшн Substring? Если вы пытаетесь избавиться от спецификации, есть гораздо лучшие способы сделать это (например, указать, что она исключена из кодировки).
Показать ещё 12 комментариев
44

ForEach для IEnumerables

public static class FrameworkExtensions
{
    // a map function
    public static void ForEach<T>(this IEnumerable<T> @enum, Action<T> mapFunction)
    {
        foreach (var item in @enum) mapFunction(item);
    }
}

Наивный пример:

var buttons = GetListOfButtons() as IEnumerable<Button>;

// click all buttons
buttons.ForEach(b => b.Click());

Пример охлаждения:

// no need to type the same assignment 3 times, just
// new[] up an array and use foreach + lambda
// everything is properly inferred by csc :-)
new { itemA, itemB, itemC }
    .ForEach(item => {
        item.Number = 1;
        item.Str = "Hello World!";
    });

Примечание:

Это не похоже на Select, потому что Select ожидает, что ваша функция вернет что-то, как для преобразования в другой список.

ForEach просто позволяет выполнять что-либо для каждого из элементов без каких-либо преобразований/манипуляций с данными.

Я сделал это, чтобы я мог программировать в более функциональном стиле, и я был удивлен, что List имеет ForEach, в то время как IEnumerable этого не делает.

Поместите это в проект codeplex

  • 0
    Можем ли мы использовать код в проекте codeplex?
  • 0
    Это похоже на Ruby .each rightÉ
Показать ещё 11 комментариев
41

У меня есть метод расширения для регистрации исключений:

public static void Log(this Exception obj)
{
  //your logging logic here
}

И он используется следующим образом:

try
{
    //Your stuff here
}
catch(Exception ex)
{
    ex.Log();
}

[извините за отправку дважды; 2-й лучше разработан: -)]

  • 2
    Стоит ли читать публичный статический журнал void (это исключение obj) {} может быть?
  • 0
    Я думаю, что это хорошо для исключений BCL или сторонних производителей, но если вы используете собственные типы исключений, вы можете поместить запись в базовый класс исключений. Таким образом, вам не нужно забывать вызывать Log ().
41

Мои расширения преобразования, которые позволяют вам делать:

int i = myString.To<int>();

Вот он, как опубликовано на TheSoftwareJedi.com

public static T To<T>(this IConvertible obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

public static T ToOrDefault<T>
             (this IConvertible obj)
{
    try
    {
        return To<T>(obj);
    }
    catch
    {
        return default(T);
    }
}

public static bool ToOrDefault<T>
                    (this IConvertible obj,
                     out T newObj)
{
    try
    {
        newObj = To<T>(obj); 
        return true;
    }
    catch
    {
        newObj = default(T); 
        return false;
    }
}

public static T ToOrOther<T>
                       (this IConvertible obj,
                       T other)
{
  try
  {
      return To<T>obj);
  }
  catch
  {
      return other;
  }
}

public static bool ToOrOther<T>
                         (this IConvertible obj,
                         out T newObj,
                         T other)
{
    try
    {
        newObj = To<T>(obj);
        return true;
    }
    catch
    {
        newObj = other;
        return false;
    }
}

public static T ToOrNull<T>
                      (this IConvertible obj)
                      where T : class
{
    try
    {
        return To<T>(obj);
    }
    catch
    {
        return null;
    }
}

public static bool ToOrNull<T>
                  (this IConvertible obj,
                  out T newObj)
                  where T : class
{
    try
    {
        newObj = To<T>(obj);
        return true;
    }
    catch
    {
        newObj = null;
        return false;
    }
}

Вы можете запросить по умолчанию (вызывает пустой конструктор или "0" для чисел) при сбое, указать значение "по умолчанию" (я называю это "другим" ) или запросить нуль (где T: class). Я также предоставил обе модели молчаливых исключений и типичную модель TryParse, которая возвращает bool с указанием предпринятого действия, а параметр out содержит новое значение. Поэтому наш код может делать такие вещи

int i = myString.To<int>();
string a = myInt.ToOrDefault<string>();
//note type inference
DateTime d = myString.ToOrOther(DateTime.MAX_VALUE);
double d;
//note type inference
bool didItGiveDefault = myString.ToOrDefault(out d);
string s = myDateTime.ToOrNull<string>();

Я не мог получить Nullable типы, чтобы ввернуться во все это очень чисто. Я пробовал около 20 минут, прежде чем я бросил полотенце.

  • 0
    Можем ли мы использовать код в проекте Codeplex?
  • 64
    Лично я не фанат кода, который пытается / ловит, чтобы определить результат. Try / catch следует использовать для ошибок, которые происходят за пределами предполагаемой логики, IMO. Hmmmmm
Показать ещё 4 комментария
39
public static class StringExtensions {

    /// <summary>
    /// Parses a string into an Enum
    /// </summary>
    /// <typeparam name="T">The type of the Enum</typeparam>
    /// <param name="value">String value to parse</param>
    /// <returns>The Enum corresponding to the stringExtensions</returns>
    public static T EnumParse<T>(this string value) {
        return StringExtensions.EnumParse<T>(value, false);
    }

    public static T EnumParse<T>(this string value, bool ignorecase) {

        if (value == null) {
            throw new ArgumentNullException("value");
        }

        value = value.Trim();

        if (value.Length == 0) {
            throw new ArgumentException("Must specify valid information for parsing in the string.", "value");
        }

        Type t = typeof(T);

        if (!t.IsEnum) {
            throw new ArgumentException("Type provided must be an Enum.", "T");
        }

        return (T)Enum.Parse(t, value, ignorecase);
    }
}

Полезно разбирать строку в Enum.

public enum TestEnum
{
    Bar,
    Test
}

public class Test
{
    public void Test()
    {
        TestEnum foo = "Test".EnumParse<TestEnum>();
    }
 }

Кредит переходит на Скотт Дорман

--- Редактировать проект Codeplex ---

Я спросил Скотта Дормана, не возражает ли он нам опубликовать его код в проекте Codeplex. Это ответ, который я получил от него:

Спасибо за хедз-ап как за сообщение SO, так и за проект CodePlex. Я подтвердил ваш ответ на вопрос. Да, этот код эффективно находится в общественном достоянии в настоящее время под лицензией CodeProject Open (http://www.codeproject.com/info/cpol10.aspx).

У меня нет проблем с включением в проект CodePlex, и если вы хотите добавить меня в проект (имя пользователя - sdorman), я добавлю этот метод плюс некоторые дополнительные вспомогательные методы перечисления.

  • 0
    Этот сценарий синтаксического анализа встречается все время ... должен поместить это в мою библиотеку :-)
  • 0
    Вау, я писал методы для сопоставления строк с перечислениями (только начал использовать .NET). Спасибо, это абсолютно поможет!
Показать ещё 5 комментариев
31

Я считаю, что это очень полезно:

public static class PaulaBean
{
    private static String paula = "Brillant";
    public static String GetPaula<T>(this T obj) {
        return paula;
    }
}

Вы можете использовать его в CodePlex.

  • 2
    Может ли кто-то быть достаточно добрым, чтобы объяснить это менее одаренным из нас?
  • 4
    thedailywtf.com/articles/the_brillant_paula_bean.aspx
Показать ещё 1 комментарий
30

DateTimeExtensions

Примеры:

DateTime firstDayOfMonth = DateTime.Now.First();
DateTime lastdayOfMonth = DateTime.Now.Last();
DateTime lastFridayInMonth = DateTime.Now.Last(DayOfWeek.Friday);
DateTime nextFriday = DateTime.Now.Next(DayOfWeek.Friday);
DateTime lunchTime = DateTime.Now.SetTime(11, 30);
DateTime noonOnFriday = DateTime.Now.Next(DayOfWeek.Friday).Noon();
DateTime secondMondayOfMonth = DateTime.Now.First(DayOfWeek.Monday).Next(DayOfWeek.Monday).Midnight();
  • 5
    Я бы предложил переименовать «SetTime» в «WithTime», так как он фактически не устанавливает его в существующее значение. Хотя в остальном приятно.
  • 1
    Согласитесь, «WithTime» звучит лучше ...
Показать ещё 3 комментария
29

Здесь используется символ to-and-from для римских цифр. Не часто используется, но может быть удобно. Использование:

if ("IV".IsValidRomanNumeral())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral());
Console.WriteLine(3888.ToRomanNumeralString());

Источник:

    public static class RomanNumeralExtensions
    {
        private const int NumberOfRomanNumeralMaps = 13;

        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }
    }
  • 0
    Не часто, но очень круто!
  • 26
    Неудивительно, что империя пала.
Показать ещё 1 комментарий
29

Вот один, который я часто использую для форматирования презентации.

public static string ToTitleCase(this string mText)
{
    if (mText == null) return mText;

    System.Globalization.CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
    System.Globalization.TextInfo textInfo = cultureInfo.TextInfo;

    // TextInfo.ToTitleCase only operates on the string if is all lower case, otherwise it returns the string unchanged.
    return textInfo.ToTitleCase(mText.ToLower());
}
  • 0
    Ух, обработка исключений Pokemon собирается скрыть такие проблемы, как ThreadAbortException и т. Д. Пожалуйста, поймайте что-то конкретное.
29

gitorious.org/cadenza - полная библиотека некоторых из наиболее полезных методов расширения, которые я видел.

  • 0
    12 довольно базовых методов расширения. Я немного не в восторге от монокамен.
  • 0
    (Я говорю о выпущенной версии, а не той, которую вам нужно использовать для контроля версий)
Показать ещё 2 комментария
24

Для элементов управления Winform:

/// <summary>
/// Returns whether the function is being executed during design time in Visual Studio.
/// </summary>
public static bool IsDesignTime(this Control control)
{
    if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
    {
        return true;
    }

    if (control.Site != null && control.Site.DesignMode)
    {
        return true;
    }

    var parent = control.Parent;
    while (parent != null)
    {
        if (parent.Site != null && parent.Site.DesignMode)
        {
            return true;
        }
        parent = parent.Parent;
    }
    return false;
}

/// <summary>
/// Sets the DropDownWidth to ensure that no item text is cut off.
/// </summary>
public static void SetDropDownWidth(this ComboBox comboBox)
{
    var g = comboBox.CreateGraphics();
    var font = comboBox.Font;
    float maxWidth = 0;

    foreach (var item in comboBox.Items)
    {
        maxWidth = Math.Max(maxWidth, g.MeasureString(item.ToString(), font).Width);
    }

    if (comboBox.Items.Count > comboBox.MaxDropDownItems)
    {
        maxWidth += SystemInformation.VerticalScrollBarWidth;
    }

    comboBox.DropDownWidth = Math.Max(comboBox.Width, Convert.ToInt32(maxWidth));
}

Использование IsDesignTime:

public class SomeForm : Form
{
    public SomeForm()
    {
        InitializeComponent();

        if (this.IsDesignTime())
        {
            return;
        }

        // Do something that makes the visual studio crash or hang if we're in design time,
        // but any other time executes just fine
    }
}

SetDropdownWidth Использование:

ComboBox cbo = new ComboBox { Width = 50 };
cbo.Items.Add("Short");
cbo.Items.Add("A little longer");
cbo.Items.Add("Holy cow, this is a really, really long item. How in the world will it fit?");
cbo.SetDropDownWidth();

Я забыл упомянуть, не стесняйтесь использовать их на Codeplex...

  • 1
    Как уже упоминалось, это только для WinForms. Он может работать с WPF, но есть проблемы (описано в комментарии о WPF на msdn.microsoft.com/en-us/library/… ). Лучшее решение для WPF, которое я нашел, описано в geekswithblogs.net/lbugnion/archive/2009/09/05/… (хотя, поскольку это статическое свойство, оно не работает как метод расширения.)
24

Удобный способ работы с размерами:

public static class Extensions {
    public static int K(this int value) {
        return value * 1024;
    }
    public static int M(this int value) {
        return value * 1024 * 1024;
    }
}

public class Program {
    public void Main() {
        WSHttpContextBinding serviceMultipleTokenBinding = new WSHttpContextBinding() {
            MaxBufferPoolSize = 2.M(), // instead of 2097152
            MaxReceivedMessageSize = 64.K(), // instead of 65536
        };
    }
}
  • 0
    На мой взгляд, это действительно плохой стиль кодирования. Вместо этого следует использовать константы, а не запутанную логику.
23

ThrowIfArgumentIsNull - отличный способ сделать эту нулевую проверку, которую мы все должны делать.

public static class Extensions
{
    public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class
    {
        if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null");
    }
}

Ниже приведен способ его использования, и он работает со всеми классами в вашем пространстве имен или там, где вы используете пространство имён внутри.

internal class Test
{
    public Test(string input1)
    {
        input1.ThrowIfArgumentIsNull("input1");
    }
}

Хорошо использовать этот код в проекте CodePlex.

  • 0
    Мне это тоже нравится, у Джона это есть, и я использую что-то похожее от Umbrella, которое может оставить часть ArgumentIs.
  • 0
    Да уж! это тоже метод расширения kewl :)
Показать ещё 4 комментария
21

Я пропускаю Visual Basic With statement при переходе на С#, так что вот оно:

public static void With<T>(this T obj, Action<T> act) { act(obj); }

А вот как использовать его в С#:

someVeryVeryLonggggVariableName.With(x => {
    x.Int = 123;
    x.Str = "Hello";
    x.Str2 = " World!";
});

Сохраняет много ввода!

Сравните это с:

someVeryVeryLonggggVariableName.Int = 123;
someVeryVeryLonggggVariableName.Str = "Hello";
someVeryVeryLonggggVariableName.Str2 = " World!";

введите проект codeplex

  • 4
    Просто предположение, но подумайте о том, что произойдет, если ваш T является структурой.
  • 0
    Не знаю, но, возможно, он должен иметь, где T: класс там.
Показать ещё 10 комментариев
18

Принимает CamelCaseWord или PascalCaseWord и "разглашает" его, т.е. camelCaseWord = > camel Case Word

public static string Wordify( this string camelCaseWord )
{
    // if the word is all upper, just return it
    if( !Regex.IsMatch( camelCaseWord, "[a-z]" ) )
        return camelCaseWord;

    return string.Join( " ", Regex.Split( camelCaseWord, @"(?<!^)(?=[A-Z])" ) );
}

Я часто использую его в сочетании с Capize

public static string Capitalize( this string word )
{
    return word[0].ToString( ).ToUpper( ) + word.Substring( 1 );
}

Пример использования

SomeEntityObject entity = DataAccessObject.GetSomeEntityObject( id );
List<PropertyInfo> properties = entity.GetType().GetPublicNonCollectionProperties( );

// wordify the property names to act as column headers for an html table or something
List<string> columns = properties.Select( p => p.Name.Capitalize( ).Wordify( ) ).ToList( );

Свободно использовать в проекте codeplex

  • 0
    Aggregate in Capitalize очень плохо влияет на производительность, потому что он создает много строковых экземпляров. Почему бы не использовать word.Substring (1) вместо этого?
17

Я нашел этот полезный

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq)
{
    return pSeq ?? Enumerable.Empty<T>();
}

Он удаляет нулевую проверку в вызывающем коде. Теперь вы можете сделать

MyList.EmptyIfNull().Where(....)
  • 0
    Да, если кто-то забыл «Null Object Pattern», этот метод полезен для его исправления. Коллекция никогда не должна быть нулевой.
  • 0
    Это меня немного пугает
16

Преобразуйте двойную строку в строку, форматированную с использованием указанной культуры:

public static class ExtensionMethods 
{
  public static string ToCurrency(this double value, string cultureName)
  {
    CultureInfo currentCulture = new CultureInfo(cultureName);
    return (string.Format(currentCulture, "{0:C}", value));
  }
}

Пример:

double test = 154.20;
string testString = test.ToCurrency("en-US"); // $154.20
  • 13
    Вы должны использовать десятичную для валюты, иначе вы получите проблемы с округлением
  • 0
    Как насчет использования Enum в параметре вместо простой строки
Показать ещё 1 комментарий
15

Здесь я только что создал сегодня.

// requires .NET 4

public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
        TReturn elseValue = default(TReturn)) where TIn : class
    { return obj != null ? func(obj) : elseValue; }

// versions for CLR 2, which doesn't support optional params

public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
        TReturn elseValue) where TIn : class
    { return obj != null ? func(obj) : elseValue; }
public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func)
        where TIn : class
    { return obj != null ? func(obj) : default(TReturn); }

Это позволяет вам сделать это:

var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());

который является более свободным и (IMO) легче читать, чем это:

var lname = (thingy != null ? thingy.Name : null) != null
    ? thingy.Name.ToLower() : null;
  • 1
    Что если я хочу thingy.NullOr(t => t.Count) , где Count - это int? Вы должны вернуть default(TReturn) а не null, таким образом, вам не понадобится ограничение class и оно будет работать и для типов значений.
  • 2
    TIn должен быть классом, иначе весь этот метод расширения не имеет смысла (типы значений не могут быть нулевыми). И ваш пример с t.Count работает с вышеуказанным методом расширения. Не могли бы вы взглянуть еще раз?
Показать ещё 7 комментариев
15

Ниже приведен метод , который адаптирует код Рика Страхла (и комментарии тоже), чтобы вы не угадали или не читали знак байтового байта байтового массива или текстового файла при каждом преобразовании его в строку.

Фрагмент позволяет вам просто:

byte[] buffer = File.ReadAllBytes(@"C:\file.txt");
string content = buffer.GetString();

Если вы найдете какие-либо ошибки, добавьте комментарии. Не стесняйтесь включать его в проект Codeplex.

public static class Extensions
{
    /// <summary>
    /// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
    /// Original article: http://www.west-wind.com/WebLog/posts/197245.aspx
    /// </summary>
    /// <param name="buffer">An array of bytes to convert</param>
    /// <returns>The byte as a string.</returns>
    public static string GetString(this byte[] buffer)
    {
        if (buffer == null || buffer.Length == 0)
            return "";

        // Ansi as default
        Encoding encoding = Encoding.Default;       

        /*
            EF BB BF    UTF-8 
            FF FE UTF-16    little endian 
            FE FF UTF-16    big endian 
            FF FE 00 00 UTF-32, little endian 
            00 00 FE FF UTF-32, big-endian 
         */

        if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
            encoding = Encoding.UTF8;
        else if (buffer[0] == 0xfe && buffer[1] == 0xff)
            encoding = Encoding.Unicode;
        else if (buffer[0] == 0xfe && buffer[1] == 0xff)
            encoding = Encoding.BigEndianUnicode; // utf-16be
        else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
            encoding = Encoding.UTF32;
        else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
            encoding = Encoding.UTF7;

        using (MemoryStream stream = new MemoryStream())
        {
            stream.Write(buffer, 0, buffer.Length);
            stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(stream, encoding))
            {
                return reader.ReadToEnd();
            }
        }
    }
}
  • 0
    Очень полезный метод, но я не думаю, что это должен быть метод расширения.
  • 0
    Если вы пишете текстовый редактор, он, вероятно, требует метода расширения, но я согласен, что большую часть времени это, вероятно, не более чем статический закрытый метод
14

Это раздражало меня тем, что LINQ дает мне OrderBy, который принимает класс, реализующий IComparer в качестве аргумента, но не поддерживает передачу простой анонимной функции сопоставления. Я исправил это.

Этот класс создает IComparer из вашей функции сравнения...

/// <summary>
///     Creates an <see cref="IComparer{T}"/> instance for the given
///     delegate function.
/// </summary>
internal class ComparerFactory<T> : IComparer<T>
{
    public static IComparer<T> Create(Func<T, T, int> comparison)
    {
        return new ComparerFactory<T>(comparison);
    }

    private readonly Func<T, T, int> _comparison;

    private ComparerFactory(Func<T, T, int> comparison)
    {
        _comparison = comparison;
    }

    #region IComparer<T> Members

    public int Compare(T x, T y)
    {
        return _comparison(x, y);
    }

    #endregion
}

... и эти методы расширений раскрывают мои новые перегрузки OrderBy для перечислений. Я сомневаюсь, что это работает для LINQ to SQL, но отлично подходит для LINQ to Objects.

public static class EnumerableExtensions
{
    /// <summary>
    /// Sorts the elements of a sequence in ascending order by using a specified comparison delegate.
    /// </summary>
    public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
                                                                     Func<TKey, TKey, int> comparison)
    {
        var comparer = ComparerFactory<TKey>.Create(comparison);
        return source.OrderBy(keySelector, comparer);
    }

    /// <summary>
    /// Sorts the elements of a sequence in descending order by using a specified comparison delegate.
    /// </summary>
    public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
                                                                               Func<TKey, TKey, int> comparison)
    {
        var comparer = ComparerFactory<TKey>.Create(comparison);
        return source.OrderByDescending(keySelector, comparer);
    }
}

Вы можете поместить это на codeplex, если хотите.

14

"Пожалуйста, отметьте свои ответы с принятием, чтобы поместить код в проект Codeplex".

Почему? Все материалы на этом сайте под CC-by-sa-2.5, так что просто поставьте свой проект переполнения расширений под ту же лицензию, и вы можете свободно используйте его.

В любом случае, вот функция String.Reverse, основанная на этом вопросе.

/// <summary>
/// Reverse a String
/// </summary>
/// <param name="input">The string to Reverse</param>
/// <returns>The reversed String</returns>
public static string Reverse(this string input)
{
    char[] array = input.ToCharArray();
    Array.Reverse(array);
    return new string(array);
}
  • 0
    Разве String уже не реализует IEnumerable <char>? Так что вам просто нужно сделать return new String (input.Reverse ());
  • 0
    Реализация с использованием StringBuilder должна быть быстрее.
Показать ещё 4 комментария
14

Я устал от утомительной нулевой проверки, вытягивая значения из MySqlDataReader, поэтому:

public static DateTime? GetNullableDateTime(this MySqlDataReader dr, string fieldName)
{
    DateTime? nullDate = null;
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullDate : dr.GetDateTime(fieldName);
}

public static string GetNullableString(this MySqlDataReader dr, string fieldName)
{
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? String.Empty : dr.GetString(fieldName);
}

public static char? GetNullableChar(this MySqlDataReader dr, string fieldName)
{
    char? nullChar = null;
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullChar : dr.GetChar(fieldName);
}

Конечно, это можно использовать с любым SqlDataReader.


У обоих, и у Джо были хорошие комментарии о том, как это сделать, и с тех пор у меня появилась возможность реализовать что-то подобное в другом контексте, так что вот еще одна версия:

public static int? GetNullableInt32(this IDataRecord dr, int ordinal)
{
    int? nullInt = null;
    return dr.IsDBNull(ordinal) ? nullInt : dr.GetInt32(ordinal);
}

public static int? GetNullableInt32(this IDataRecord dr, string fieldname)
{
    int ordinal = dr.GetOrdinal(fieldname);
    return dr.GetNullableInt32(ordinal);
}

public static bool? GetNullableBoolean(this IDataRecord dr, int ordinal)
{
    bool? nullBool = null;
    return dr.IsDBNull(ordinal) ? nullBool : dr.GetBoolean(ordinal);
}

public static bool? GetNullableBoolean(this IDataRecord dr, string fieldname)
{
    int ordinal = dr.GetOrdinal(fieldname);
    return dr.GetNullableBoolean(ordinal);
}
  • 2
    Это также должно работать как метод расширения для IDataReader.
  • 2
    На самом деле, сделайте параметр «this» типа IDataRecord для максимальной совместимости. В моей версии этого у меня есть перегрузка, которая принимает порядковый номер, который вызывает версия fieldName. Сохраняет «GetOrdinal» с последующим поиском по имени.
Показать ещё 7 комментариев
13

Этот для MVC добавляет возможность генерировать тэг <label /> переменной Html, доступной в каждом ViewPage. Надеюсь, это будет полезно для других, пытающихся разработать аналогичные расширения.

Применение:

<%= Html.Label("LabelId", "ForId", "Text")%>

Вывод:

<label id="LabelId" for="ForId">Text</label>

Код:

public static class HtmlHelperExtensions
{
    public static string Label(this HtmlHelper Html, string @for, string text)
    {
        return Html.Label(null, @for, text);
    }

    public static string Label(this HtmlHelper Html, string @for, string text, object htmlAttributes)
    {
        return Html.Label(null, @for, text, htmlAttributes);
    }

    public static string Label(this HtmlHelper Html, string @for, string text, IDictionary<string, object> htmlAttributes)
    {
        return Html.Label(null, @for, text, htmlAttributes);
    }

    public static string Label(this HtmlHelper Html, string id, string @for, string text)
    {
        return Html.Label(id, @for, text, null);
    }

    public static string Label(this HtmlHelper Html, string id, string @for, string text, object htmlAttributes)
    {
        return Html.Label(id, @for, text, new RouteValueDictionary(htmlAttributes));
    }

    public static string Label(this HtmlHelper Html, string id, string @for, string text, IDictionary<string, object> htmlAttributes)
    {
        TagBuilder tag = new TagBuilder("label");

        tag.MergeAttributes(htmlAttributes);

        if (!string.IsNullOrEmpty(id))
            tag.MergeAttribute("id", Html.AttributeEncode(id));

        tag.MergeAttribute("for", Html.AttributeEncode(@for));

        tag.SetInnerText(Html.Encode(text));

        return tag.ToString(TagRenderMode.Normal);
    }
}
  • 0
    Проверьте MvcContrib.FluentHtml
  • 0
    Это, вероятно, следует дублировать с Literal вместо этого.
12

Поверните это:

DbCommand command = connection.CreateCommand();
command.CommandText = "SELECT @param";

DbParameter param = command.CreateParameter();
param.ParameterName = "@param";
param.Value = "Hello World";

command.Parameters.Add(param);

... в это:

DbCommand command = connection.CreateCommand("SELECT {0}", "Hello World");

... используя этот метод расширения:

using System;
using System.Data.Common;
using System.Globalization;
using System.Reflection;

namespace DbExtensions {

   public static class Db {

      static readonly Func<DbConnection, DbProviderFactory> getDbProviderFactory;
      static readonly Func<DbCommandBuilder, int, string> getParameterName;
      static readonly Func<DbCommandBuilder, int, string> getParameterPlaceholder;

      static Db() {

         getDbProviderFactory = (Func<DbConnection, DbProviderFactory>)Delegate.CreateDelegate(typeof(Func<DbConnection, DbProviderFactory>), typeof(DbConnection).GetProperty("DbProviderFactory", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true));
         getParameterName = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterName", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null));
         getParameterPlaceholder = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterPlaceholder", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null));
      }

      public static DbProviderFactory GetProviderFactory(this DbConnection connection) {
         return getDbProviderFactory(connection);
      }

      public static DbCommand CreateCommand(this DbConnection connection, string commandText, params object[] parameters) {

         if (connection == null) throw new ArgumentNullException("connection");

         return CreateCommandImpl(GetProviderFactory(connection).CreateCommandBuilder(), connection.CreateCommand(), commandText, parameters);
      }

      private static DbCommand CreateCommandImpl(DbCommandBuilder commandBuilder, DbCommand command, string commandText, params object[] parameters) {

         if (commandBuilder == null) throw new ArgumentNullException("commandBuilder");
         if (command == null) throw new ArgumentNullException("command");
         if (commandText == null) throw new ArgumentNullException("commandText");

         if (parameters == null || parameters.Length == 0) {
            command.CommandText = commandText;
            return command;
         }

         object[] paramPlaceholders = new object[parameters.Length];

         for (int i = 0; i < paramPlaceholders.Length; i++) {

            DbParameter dbParam = command.CreateParameter();
            dbParam.ParameterName = getParameterName(commandBuilder, i);
            dbParam.Value = parameters[i] ?? DBNull.Value;
            command.Parameters.Add(dbParam);

            paramPlaceholders[i] = getParameterPlaceholder(commandBuilder, i);
         }

         command.CommandText = String.Format(CultureInfo.InvariantCulture, commandText, paramPlaceholders);

         return command;
      }
   }
}

Дополнительные методы расширения ADO.NET: DbExtensions

11

Один из моих фаворитов - расширение IsLike() на String. IsLike() соответствует VB Like operator и удобен, когда вы не хотите писать регулярное выражение для решения вашей проблемы. Использование будет примерно таким:

"abc".IsLike("a*"); // true
"Abc".IsLike("[A-Z][a-z][a-z]"); // true
"abc123".IsLike("*###"); // true
"hat".IsLike("?at"); // true
"joe".IsLike("[!aeiou]*"); // true

"joe".IsLike("?at"); // false
"joe".IsLike("[A-Z][a-z][a-z]"); // false

Здесь код

public static class StringEntentions {
    /// <summary>
    /// Indicates whether the current string matches the supplied wildcard pattern.  Behaves the same
    /// as VB "Like" Operator.
    /// </summary>
    /// <param name="s">The string instance where the extension method is called</param>
    /// <param name="wildcardPattern">The wildcard pattern to match.  Syntax matches VB Like operator.</param>
    /// <returns>true if the string matches the supplied pattern, false otherwise.</returns>
    /// <remarks>See http://msdn.microsoft.com/en-us/library/swf8kaxw(v=VS.100).aspx</remarks>
    public static bool IsLike(this string s, string wildcardPattern) {
        if (s == null || String.IsNullOrEmpty(wildcardPattern)) return false;
        // turn into regex pattern, and match the whole string with ^$
        var regexPattern = "^" + Regex.Escape(wildcardPattern) + "$";

        // add support for ?, #, *, [], and [!]
        regexPattern = regexPattern.Replace(@"\[!", "[^")
                                   .Replace(@"\[", "[")
                                   .Replace(@"\]", "]")
                                   .Replace(@"\?", ".")
                                   .Replace(@"\*", ".*")
                                   .Replace(@"\#", @"\d");

        var result = false;
        try {
            result = Regex.IsMatch(s, regexPattern);
        }
        catch (ArgumentException ex) {
            throw new ArgumentException(String.Format("Invalid pattern: {0}", wildcardPattern), ex);
        }
        return result;
    }
}
  • 1
    Очень похоже на метод, который я разместил здесь . Ваша реализация допускает более гибкие шаблоны, но моя, вероятно, быстрее;)
10

Аналогично строке As и Is выше, но глобально для всех объектов.

Это довольно просто, но я использую их для облегчения взрыва парсов с бокса.

public static class ExtensionMethods_Object
{
    [DebuggerStepThrough()]
    public static bool Is<T>(this object item) where T : class
    {
        return item is T;
    }

    [DebuggerStepThrough()]
    public static bool IsNot<T>(this object item) where T : class
    {
        return !(item.Is<T>());
    }

    [DebuggerStepThrough()]
    public static T As<T>(this object item) where T : class
    {
        return item as T;
    }
}

Я рад, что этот код используется в кодексе, действительно, он уже есть.

  • 0
    И какова цель всего этого? Почему бы просто не написать, скажем, «item as Type» вместо «item.As <Type> ()», как вы это делаете?
  • 2
    @ Kamarey Это субъективное предпочтение, но оно уменьшает запутанные паренсы, которые могут накопиться, если у вас есть несколько каст. item as Type становится (item as Type) или ((Type) item), если вам нужно использовать item в качестве типа приведения. Кроме того, слева направо сканирование элемента. Как <Тип> (). ... в некоторых запутанных случаях гораздо удобнее читать по боксу. Я сказал, что это было просто, и я согласен, что это субъективно, но я считаю, что это может быть довольно мощным в удобочитаемости кода.
Показать ещё 1 комментарий
10

Найдите больше примеров здесь: www.extensionmethod.net

9

В классе Random можно найти множество функций.

Ниже приведены некоторые методы расширения, которые я использую время от времени. При этом, помимо Next и NextDouble, класс Random дает вам NextBool, NextChar, NextDateTime, NextTimeSpan, NextDouble (принимает параметры minValue и maxValue), и мой личный фаворит: NextString. Есть больше (NextByte, NextShort, NextLong и т.д.); но они в основном для полноты и не используются так сильно. Поэтому я не включил их здесь (этот код достаточно длинный, как есть!).

// todo: implement additional CharType values (e.g., AsciiAny)
public enum CharType {
    AlphabeticLower,
    AlphabeticUpper,
    AlphabeticAny,
    AlphanumericLower,
    AlphanumericUpper,
    AlphanumericAny,
    Numeric
}

public static class RandomExtensions {
    // 10 digits vs. 52 alphabetic characters (upper & lower);
    // probability of being numeric: 10 / 62 = 0.1612903225806452
    private const double AlphanumericProbabilityNumericAny = 10.0 / 62.0;

    // 10 digits vs. 26 alphabetic characters (upper OR lower);
    // probability of being numeric: 10 / 36 = 0.2777777777777778
    private const double AlphanumericProbabilityNumericCased = 10.0 / 36.0;

    public static bool NextBool(this Random random, double probability) {
        return random.NextDouble() <= probability;
    }

    public static bool NextBool(this Random random) {
        return random.NextDouble() <= 0.5;
    }

    public static char NextChar(this Random random, CharType mode) {
        switch (mode) {
            case CharType.AlphabeticAny:
                return random.NextAlphabeticChar();
            case CharType.AlphabeticLower:
                return random.NextAlphabeticChar(false);
            case CharType.AlphabeticUpper:
                return random.NextAlphabeticChar(true);
            case CharType.AlphanumericAny:
                return random.NextAlphanumericChar();
            case CharType.AlphanumericLower:
                return random.NextAlphanumericChar(false);
            case CharType.AlphanumericUpper:
                return random.NextAlphanumericChar(true);
            case CharType.Numeric:
                return random.NextNumericChar();
            default:
                return random.NextAlphanumericChar();
        }
    }

    public static char NextChar(this Random random) {
        return random.NextChar(CharType.AlphanumericAny);
    }

    private static char NextAlphanumericChar(this Random random, bool uppercase) {
        bool numeric = random.NextBool(AlphanumericProbabilityNumericCased);

        if (numeric)
            return random.NextNumericChar();
        else
            return random.NextAlphabeticChar(uppercase);
    }

    private static char NextAlphanumericChar(this Random random) {
        bool numeric = random.NextBool(AlphanumericProbabilityNumericAny);

        if (numeric)
            return random.NextNumericChar();
        else
            return random.NextAlphabeticChar(random.NextBool());
    }

    private static char NextAlphabeticChar(this Random random, bool uppercase) {
        if (uppercase)
            return (char)random.Next(65, 91);
        else
            return (char)random.Next(97, 123);
    }

    private static char NextAlphabeticChar(this Random random) {
        return random.NextAlphabeticChar(random.NextBool());
    }

    private static char NextNumericChar(this Random random) {
        return (char)random.Next(48, 58);
    }

    public static DateTime NextDateTime(this Random random, DateTime minValue, DateTime maxValue) {
        return DateTime.FromOADate(
            random.NextDouble(minValue.ToOADate(), maxValue.ToOADate())
        );
    }

    public static DateTime NextDateTime(this Random random) {
        return random.NextDateTime(DateTime.MinValue, DateTime.MaxValue);
    }

    public static double NextDouble(this Random random, double minValue, double maxValue) {
        if (maxValue < minValue)
            throw new ArgumentException("Minimum value must be less than maximum value.");

        double difference = maxValue - minValue;
        if (!double.IsInfinity(difference))
            return minValue + (random.NextDouble() * difference);

        else {
            // to avoid evaluating to Double.Infinity, we split the range into two halves:
            double halfDifference = (maxValue * 0.5) - (minValue * 0.5);

            // 50/50 chance of returning a value from the first or second half of the range
            if (random.NextBool())
                return minValue + (random.NextDouble() * halfDifference);
            else
                return (minValue + halfDifference) + (random.NextDouble() * halfDifference);
        }
    }

    public static string NextString(this Random random, int numChars, CharType mode) {
        char[] chars = new char[numChars];

        for (int i = 0; i < numChars; ++i)
            chars[i] = random.NextChar(mode);

        return new string(chars);
    }

    public static string NextString(this Random random, int numChars) {
        return random.NextString(numChars, CharType.AlphanumericAny);
    }

    public static TimeSpan NextTimeSpan(this Random random, TimeSpan minValue, TimeSpan maxValue) {
        return TimeSpan.FromMilliseconds(
            random.NextDouble(minValue.TotalMilliseconds, maxValue.TotalMilliseconds)
        );
    }

    public static TimeSpan NextTimeSpan(this Random random) {
        return random.NextTimeSpan(TimeSpan.MinValue, TimeSpan.MaxValue);
    }
}
9

IEnumerable<> Перемешать

Я использовал Fisher-Yates алгоритм для реализации функции тасования.

Используя yield return и разбивая код на две функции, он обеспечивает правильную проверку аргументов и отсроченное выполнение. (спасибо, Dan, указав этот недостаток в моей первой версии)

static public IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    if (source == null) throw new ArgumentNullException("source");

    return ShuffleIterator(source);
}

static private IEnumerable<T> ShuffleIterator<T>(this IEnumerable<T> source)
{
    T[] array = source.ToArray();
    Random rnd = new Random();          
    for (int n = array.Length; n > 1;)
    {
        int k = rnd.Next(n--); // 0 <= k < n

        //Swap items
        if (n != k)
        {
            T tmp = array[k];
            array[k] = array[n];
            array[n] = tmp;
        }
    }

    foreach (var item in array) yield return item;
}
  • 1
    Если вы намереваетесь использовать этот метод в запросах LINQ, вы можете рассмотреть возможность реализации класса ShuffledEnumerable который только выполняет эту работу (и, возможно, кэширует его) в GetEnumerator чтобы обеспечить ленивую оценку, известную как отложенное выполнение. В противном случае, если кто-то вызывает, например, var shuffledNames = myObjects.Select(x => x.Name).Distinct().Shuffle(); операция будет выполнена немедленно, что может не соответствовать ожиданиям. Хороший ответ, хотя!
  • 1
    @ Дан: Это отличный момент. Однако существует элегантный способ использовать отложенное выполнение без явно объявленного класса. yield return решает проблему. Я отредактирую свой ответ.
Показать ещё 3 комментария
9

Еще один полезный для меня:

/// <summary>
/// Converts any type in to an Int32
/// </summary>
/// <typeparam name="T">Any Object</typeparam>
/// <param name="value">Value to convert</param>
/// <returns>The integer, 0 if unsuccessful</returns>
public static int ToInt32<T>(this T value)
{
  int result;
  if (int.TryParse(value.ToString(), out result))
  {
    return result;
  }
  return 0;
}

/// <summary>
/// Converts any type in to an Int32 but if null then returns the default
/// </summary>
/// <param name="value">Value to convert</param>
/// <typeparam name="T">Any Object</typeparam>
/// <param name="defaultValue">Default to use</param>
/// <returns>The defaultValue if unsuccessful</returns>
public static int ToInt32<T>(this T value, int defaultValue)
{
  int result;
  if (int.TryParse(value.ToString(), out result))
  {
    return result;
  }
  return defaultValue;
}

Пример:

int number = "123".ToInt32();

или

int badNumber = "a".ToInt32(100); // Returns 100 since a is nan
  • 0
    Да, тот же ToInt64, ToFloat и т. Д. Вы можете исключить if и сбить его до одного возврата, если хотите.
  • 0
    Нет примера кода !!!
Показать ещё 6 комментариев
8

Я использую их в своих проектах Silverlight:

public static void Show(this UIElement element)
{
    element.Visibility = Visibility.Visible;
}

public static void Hide(this UIElement element)
{
    element.Visibility = Visibility.Collapsed;
}
8

Связанные с Timespan расширения, например:

public static TimeSpan Seconds(this int seconds)
{
  return TimeSpan.FromSeconds(seconds);
}

public static TimeSpan Minutes(this int minutes)
{
  return TimeSpan.FromMinutes(minutes);
}

Это позволяет использовать:

1.Seconds()
20.Minutes()

Блокировать расширения как:

public static IDisposable GetReadLock(this ReaderWriterLockSlim slimLock)
{
  slimLock.EnterReadLock();
  return new DisposableAction(slimLock.ExitReadLock);
}

public static IDisposable GetWriteLock(this ReaderWriterLockSlim slimLock)
{
  slimLock.EnterWriteLock();
  return new DisposableAction(slimLock.ExitWriteLock);
}

public static IDisposable GetUpgradeableReadLock(this ReaderWriterLockSlim slimLock)
{
  slimLock.EnterUpgradeableReadLock();
  return new DisposableAction(slimLock.ExitUpgradeableReadLock);
}

Это позволяет использовать блокировки типа:

using (lock.GetUpgradeableReadLock())
{
  // try read
  using (lock.GetWriteLock())
  {
    //do write
  }
}

И многие другие из Lokad Shared Libraries

8

Некоторые из моих лучших расширений метода (у меня много!):

public static T ToEnum<T>(this string str) where T : struct
{
    return (T)Enum.Parse(typeof(T), str);
}

//DayOfWeek sunday =  "Sunday".ToEnum<DayOfWeek>();

public static string ToString<T>(this IEnumerable<T> collection, string separator)
{
    return ToString(collection, t => t.ToString(), separator);
}

public static string ToString<T>(this IEnumerable<T> collection, Func<T, string> stringElement, string separator)
{
    StringBuilder sb = new StringBuilder();
    foreach (var item in collection)
    {
        sb.Append(stringElement(item));
        sb.Append(separator);
    }
    return sb.ToString(0, Math.Max(0, sb.Length - separator.Length));  // quita el ultimo separador
}

//new []{1,2,3}.ToString(i=>i*2, ", ")  --> "2, 4, 6"

Кроме того, следующие из них предназначены для продолжения в одной строке практически в любой ситуации, не объявляя новые переменные, а затем удаляя состояние:

public static R Map<T, R>(this T t, Func<T, R> func)
{
    return func(t);
}

ExpensiveFindWally().Map(wally=>wally.FirstName + " " + wally.LastName)

public static R TryCC<T, R>(this T t, Func<T, R> func)
    where T : class
    where R : class
{
    if (t == null) return null;
    return func(t);
}

public static R? TryCS<T, R>(this T t, Func<T, R> func)
    where T : class
    where R : struct
{
    if (t == null) return null;
    return func(t);
}

public static R? TryCS<T, R>(this T t, Func<T, R?> func)
    where T : class
    where R : struct
{
    if (t == null) return null;
    return func(t);
}

public static R TrySC<T, R>(this T? t, Func<T, R> func)
    where T : struct
    where R : class
{
    if (t == null) return null;
    return func(t.Value);
}

public static R? TrySS<T, R>(this T? t, Func<T, R> func)
    where T : struct
    where R : struct
{
    if (t == null) return null;
    return func(t.Value);
}

public static R? TrySS<T, R>(this T? t, Func<T, R?> func)
    where T : struct
    where R : struct
{
    if (t == null) return null;
    return func(t.Value);
}

//int? bossNameLength =  Departament.Boss.TryCC(b=>b.Name).TryCS(s=>s.Length);


public static T ThrowIfNullS<T>(this T? t, string mensaje)
    where T : struct
{
    if (t == null)
        throw new NullReferenceException(mensaje);
    return t.Value;
}

public static T ThrowIfNullC<T>(this T t, string mensaje)
    where T : class
{
    if (t == null)
        throw new NullReferenceException(mensaje);
    return t;
}

public static T Do<T>(this T t, Action<T> action)
{
    action(t);
    return t;
}

//Button b = new Button{Content = "Click"}.Do(b=>Canvas.SetColumn(b,2));

public static T TryDo<T>(this T t, Action<T> action) where T : class
{
    if (t != null)
        action(t);
    return t;
}

public static T? TryDoS<T>(this T? t, Action<T> action) where T : struct
{
    if (t != null)
        action(t.Value);
    return t;
}

Надеюсь, что это не похоже на Марс:)

  • 0
    Можем ли мы использовать код в extensionoverflow на CodePlex?
8

Я разочарован тем, что .NET Framework предпочитает, чтобы файлы и каталоги представлялись как строки, а не объекты, и что типы FileInfo и DirectoryInfo не так сильны, как я бы хотел. Итак, я начал писать быстрые методы расширения по мере необходимости, например:

public static FileInfo SetExtension(this FileInfo fileInfo, string extension)
{
    return new FileInfo(Path.ChangeExtension(fileInfo.FullName, extension));
}

public static FileInfo SetDirectory(this FileInfo fileInfo, string directory)
{
    return new FileInfo(Path.Combine(directory, fileInfo.Name));
}

Да, вы можете поместить это в codeplex

  • 1
    FileInfo и DirectoryInfo довольно медленные по сравнению с их строковыми аналогами File и Directory. Вы могли бы хотеть профилировать те.
7

Некоторые функции Date:

public static bool IsFuture(this DateTime date, DateTime from)
{
    return date.Date > from.Date;
}

public static bool IsFuture(this DateTime date)
{
    return date.IsFuture(DateTime.Now);
}

public static bool IsPast(this DateTime date, DateTime from)
{
    return date.Date < from.Date;
}

public static bool IsPast(this DateTime date)
{
    return date.IsPast(DateTime.Now);
}
  • 1
    У нас есть несколько похожих в нашей кодовой базе: IsBefore (), IsOnOrBefore (), IsOnOrAfter (), IsAfter (), IsBeforeToday (), IsAfterToday (). Они оборачивают довольно тривиальный код, но они значительно улучшают читаемость.
7

Я только что просмотрел все 4 страницы этого, и я был довольно удивлен, что я не видел этого, чтобы сократить проверку на InvokeRequired:

using System;
using System.Windows.Forms;

/// <summary>
/// Extension methods acting on Control objects.
/// </summary>
internal static class ControlExtensionMethods
{
    /// <summary>
    /// Invokes the given action on the given control UI thread, if invocation is needed.
    /// </summary>
    /// <param name="control">Control on whose UI thread to possibly invoke.</param>
    /// <param name="action">Action to be invoked on the given control.</param>
    public static void MaybeInvoke(this Control control, Action action)
    {
        if (control != null && control.InvokeRequired)
        {
            control.Invoke(action);
        }
        else
        {
            action();
        }
    }

    /// <summary>
    /// Maybe Invoke a Func that returns a value.
    /// </summary>
    /// <typeparam name="T">Return type of func.</typeparam>
    /// <param name="control">Control on which to maybe invoke.</param>
    /// <param name="func">Function returning a value, to invoke.</param>
    /// <returns>The result of the call to func.</returns>
    public static T MaybeInvoke<T>(this Control control, Func<T> func)
    {
        if (control != null && control.InvokeRequired)
        {
            return (T)(control.Invoke(func));
        }
        else
        {
            return func();
        }
    }
}

Использование:

myForm.MaybeInvoke(() => this.Text = "Hello world");

// Sometimes the control might be null, but that okay.
var dialogResult = this.Parent.MaybeInvoke(() => MessageBox.Show(this, "Yes or no?", "Choice", MessageBoxButtons.YesNo));
7

Двоичный поиск:

public static T BinarySearch<T, TKey>(this IList<T> list, Func<T, TKey> keySelector, TKey key)
        where TKey : IComparable<TKey>
{
    int min = 0;
    int max = list.Count;
    int index = 0;
    while (min < max)
    {
        int mid = (max + min) / 2;
        T midItem = list[mid];
        TKey midKey = keySelector(midItem);
        int comp = midKey.CompareTo(key);
        if (comp < 0)
        {
            min = mid + 1;
        }
        else if (comp > 0)
        {
            max = mid - 1;
        }
        else
        {
            return midItem;
        }
    }
    if (min == max &&
        keySelector(list[min]).CompareTo(key) == 0)
    {
        return list[min];
    }
    throw new InvalidOperationException("Item not found");
}

Использование (при условии, что список отсортирован по идентификатору):

var item = list.BinarySearch(i => i.Id, 42);

Тот факт, что он генерирует исключение InvalidOperationException, может показаться странным, но это то, что Enumerable.First делает, когда нет соответствующего элемента.

7

Иногда его удобно выписывать строку в выбранном элементе в списке с пользовательским разделителем.

Например, если у вас есть List<Person> и вы хотите вычеркнуть последнее имя, разделенное запятой, вы можете сделать это.

string result = string.Empty;
foreach (var person in personList) {
   result += person.LastName + ", ";
}
result = result.Substring(0, result.Length - 2);
return result;

Или вы можете использовать этот удобный метод расширения

public static string Join<T>(this IEnumerable<T> collection, Func<T, string> func, string separator)
{
  return String.Join(separator, collection.Select(func).ToArray());
}

И используйте его вот так

personList.Join(x => x.LastName, ", ");

Что дает тот же результат, в этом случае список последних имен, разделенных запятой.

  • 0
    Что если список пуст в первом коде?
  • 1
    Я назвал свою версию этой ToDelimitedString чтобы избежать путаницы со встроенным методом LINQ Join.
7
public static class EnumerableExtensions
{
    [Pure]
    public static U MapReduce<T, U>(this IEnumerable<T> enumerable, Func<T, U> map, Func<U, U, U> reduce)
    {
        CodeContract.RequiresAlways(enumerable != null);
        CodeContract.RequiresAlways(enumerable.Skip(1).Any());
        CodeContract.RequiresAlways(map != null);
        CodeContract.RequiresAlways(reduce != null);
        return enumerable.AsParallel().Select(map).Aggregate(reduce);
    }
    [Pure]
    public static U MapReduce<T, U>(this IList<T> list, Func<T, U> map, Func<U, U, U> reduce)
    {
        CodeContract.RequiresAlways(list != null);
        CodeContract.RequiresAlways(list.Count >= 2);
        CodeContract.RequiresAlways(map != null);
        CodeContract.RequiresAlways(reduce != null);
        U result = map(list[0]);
        for (int i = 1; i < list.Count; i++)
        {
            result = reduce(result,map(list[i]));
        }
        return result;
    }

    //Parallel version; creates garbage
    [Pure]
    public static U MapReduce<T, U>(this IList<T> list, Func<T, U> map, Func<U, U, U> reduce)
    {
        CodeContract.RequiresAlways(list != null);
        CodeContract.RequiresAlways(list.Skip(1).Any());
        CodeContract.RequiresAlways(map != null);
        CodeContract.RequiresAlways(reduce != null);

        U[] mapped = new U[list.Count];
        Parallel.For(0, mapped.Length, i =>
            {
                mapped[i] = map(list[i]);
            });
        U result = mapped[0];
        for (int i = 1; i < list.Count; i++)
        {
            result = reduce(result, mapped[i]);
        }
        return result;
    }

}
  • 0
    +1 за использование малоизвестных API-интерфейсов разработки .NET 4.0.
  • 3
    Не опасно ли уже перечислять «перечислимое», вызывая «Count» для проверки контракта? Или это не проверка во время выполнения?
Показать ещё 1 комментарий
7

НТН. Это некоторые из моих основных.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace Insert.Your.Namespace.Here.Helpers
{
    public static class Extensions
    {
        public static bool IsNullOrEmpty<T>(this IEnumerable<T> iEnumerable)
        {
            // Cheers to Joel Mueller for the bugfix. Was .Count(), now it .Any()
            return iEnumerable == null ||
                   !iEnumerable.Any();
        }

        public static IList<T> ToListIfNotNullOrEmpty<T>(this IList<T> iList)
        {
            return iList.IsNullOrEmpty() ? null : iList;
        }

        public static PagedList<T> ToPagedListIfNotNullOrEmpty<T>(this PagedList<T> pagedList)
        {
            return pagedList.IsNullOrEmpty() ? null : pagedList;
        }

        public static string ToPluralString(this int value)
        {
            return value == 1 ? string.Empty : "s";
        }

        public static string ToReadableTime(this DateTime value)
        {
            TimeSpan span = DateTime.Now.Subtract(value);
            const string plural = "s";


            if (span.Days > 7)
            {
                return value.ToShortDateString();
            }

            switch (span.Days)
            {
                case 0:
                    switch (span.Hours)
                    {
                        case 0:
                            if (span.Minutes == 0)
                            {
                                return span.Seconds <= 0
                                           ? "now"
                                           : string.Format("{0} second{1} ago",
                                                           span.Seconds,
                                                           span.Seconds != 1 ? plural : string.Empty);
                            }
                            return string.Format("{0} minute{1} ago",
                                                 span.Minutes,
                                                 span.Minutes != 1 ? plural : string.Empty);
                        default:
                            return string.Format("{0} hour{1} ago",
                                                 span.Hours,
                                                 span.Hours != 1 ? plural : string.Empty);
                    }
                default:
                    return string.Format("{0} day{1} ago",
                                         span.Days,
                                         span.Days != 1 ? plural : string.Empty);
            }
        }

        public static string ToShortGuidString(this Guid value)
        {
            return Convert.ToBase64String(value.ToByteArray())
                .Replace("/", "_")
                .Replace("+", "-")
                .Substring(0, 22);
        }

        public static Guid FromShortGuidString(this string value)
        {
            return new Guid(Convert.FromBase64String(value.Replace("_", "/")
                                                         .Replace("-", "+") + "=="));
        }

        public static string ToStringMaximumLength(this string value, int maximumLength)
        {
            return ToStringMaximumLength(value, maximumLength, "...");
        }

        public static string ToStringMaximumLength(this string value, int maximumLength, string postFixText)
        {
            if (string.IsNullOrEmpty(postFixText))
            {
                throw new ArgumentNullException("postFixText");
            }

            return value.Length > maximumLength
                       ? string.Format(CultureInfo.InvariantCulture,
                                       "{0}{1}",
                                       value.Substring(0, maximumLength - postFixText.Length),
                                       postFixText)
                       :
                           value;
        }

        public static string SlugDecode(this string value)
        {
            return value.Replace("_", " ");
        }

        public static string SlugEncode(this string value)
        {
            return value.Replace(" ", "_");
        }
    }
}
  • 4
    На IsNullOrEmpty я бы не хотел называть это перечислителем на миллион предметов. Было бы перебрать все миллионы предметов, просто чтобы сказать мне, что это не пусто. Лучше: вернуть iEnumerable == null || ! IEnumerable.Any ();
  • 0
    О чувак - потрясающий соус! я никогда этого не знал! ура куча чувак. (мой пост выше отредактирован.)
Показать ещё 7 комментариев
6

При использовании словаря, где ключ является строкой, верните существующий ключ, используя поиск без учета регистра. Наш прецедент для этого был для путей к файлам.

/// <summary>
/// Gets the key using <paramref name="caseInsensitiveKey"/> from <paramref name="dictionary"/>.
/// </summary>
/// <typeparam name="T">The dictionary value.</typeparam>
/// <param name="dictionary">The dictionary.</param>
/// <param name="caseInsensitiveKey">The case insensitive key.</param>
/// <returns>
/// An existing key; or <see cref="string.Empty"/> if not found.
/// </returns>
public static string GetKeyIgnoringCase<T>(this IDictionary<string, T> dictionary, string caseInsensitiveKey)
{
    if (string.IsNullOrEmpty(caseInsensitiveKey)) return string.Empty;
    foreach (string key in dictionary.Keys)
    {
        if (key.Equals(caseInsensitiveKey, StringComparison.InvariantCultureIgnoreCase))
        {
            return key;
        }
    }
    return string.Empty;
}
  • 2
    В словаре есть отдельное свойство коллекции ключей, которое может сделать это быстрее
  • 1
    Хорошее мышление Джоэл, обновленный ответ (и мой собственный код :)
Показать ещё 2 комментария
6

Я снова и снова повторяю это снова...

public static bool EqualsIgnoreCase(this string a, string b)
{
    return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}

... затем StartsWithIgnoreCase, EndsWithIgnoreCase и ContainsIgnoreCase.

6

Я использую этот метод расширения обычно с анонимными типами, чтобы получить словарь ala ruby ​​

public static Dictionary<string, object> ToDictionary(this object o)
{
    var dictionary = new Dictionary<string, object>();

    foreach (var propertyInfo in o.GetType().GetProperties())
    {
        if (propertyInfo.GetIndexParameters().Length == 0)
        {
            dictionary.Add(propertyInfo.Name, propertyInfo.GetValue(o, null));
        }
    }

    return dictionary;
}

Вы можете использовать его

var dummy = new { color = "#000000", width = "100%", id = "myid" };
Dictionary<string, object> dict = dummy.ToDictionary();

И с расширенным методом как

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach (T item in source)
    {
        action(item);
    }
}

Вы можете сделать это

dummy.ToDictionary().ForEach((p) => Console.Write("{0}='{1}' ", p.Key, p.Value));

Выход

color = '# 000000' width = '100%' id = 'myid'

  • 0
    Вы также можете сделать: Console.Write (dummy.ToDictionary (). Select (p => string.Format (p.Key + "= '" + p.Value + "'")))); так что нет необходимости в расширении ForEach
6

Питонические методы для словарей:

/// <summary>
/// If a key exists in a dictionary, return its value, 
/// otherwise return the default value for that type.
/// </summary>
public static U GetWithDefault<T, U>(this Dictionary<T, U> dict, T key)
{
    return dict.GetWithDefault(key, default(U));
}

/// <summary>
/// If a key exists in a dictionary, return its value,
/// otherwise return the provided default value.
/// </summary>
public static U GetWithDefault<T, U>(this Dictionary<T, U> dict, T key, U defaultValue)
{
    return dict.ContainsKey(key)
        ? dict[key]
        : defaultValue;
}

Полезно, если вы хотите добавить временную метку к имени файла, чтобы гарантировать уникальность.

/// <summary>
/// Format a DateTime as a string that contains no characters
//// that are banned from filenames, such as ':'.
/// </summary>
/// <returns>YYYY-MM-DD_HH.MM.SS</returns>
public static string ToFilenameString(this DateTime dt)
{
    return dt.ToString("s").Replace(":", ".").Replace('T', '_');
}
  • 1
    Use dt.ToString("yyy-MM-dd_HH.mm.ss"); напрямую, чтобы избежать создания 2 дополнительных экземпляров String. Поскольку этот формат не включает компонент часового пояса, время в формате UTC было бы лучше с помощью dt.ToUniversalTime().ToString(...) .
  • 4
    Лучше использовать TryGetValue, вы делаете два поиска вместо одного.
6

Функция сравнения файлов/каталогов с помощью информации о файловой системе ОС. Это полезно для сравнения акций с локальными файлами.

Применение:

DirectoryInfo dir = new DirectoryInfo(@"C:\test\myShareDir");
Console.WriteLine(dir.IsSameFileAs(@"\\myMachineName\myShareDir"));

FileInfo file = new FileInfo(@"C:\test\myShareDir\file.txt");
Console.WriteLine(file.IsSameFileAs(@"\\myMachineName\myShareDir\file.txt"));

Код:

public static class FileExtensions
{
    struct BY_HANDLE_FILE_INFORMATION
    {
        public uint FileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
        public uint VolumeSerialNumber;
        public uint FileSizeHigh;
        public uint FileSizeLow;
        public uint NumberOfLinks;
        public uint FileIndexHigh;
        public uint FileIndexLow;
    }

    //
    // CreateFile constants
    //
    const uint FILE_SHARE_READ = 0x00000001;
    const uint OPEN_EXISTING = 3;
    const uint GENERIC_READ = (0x80000000);
    const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;


    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        IntPtr lpSecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        IntPtr hTemplateFile);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);

    public static bool IsSameFileAs(this FileSystemInfo file, string path)
    {
        BY_HANDLE_FILE_INFORMATION fileInfo1, fileInfo2;
        IntPtr ptr1 = CreateFile(file.FullName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);
        if ((int)ptr1 == -1)
        {
            System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            throw e;
        }
        IntPtr ptr2 = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);
        if ((int)ptr2 == -1)
        {
            System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            throw e;
        }
        GetFileInformationByHandle(ptr1, out fileInfo1);
        GetFileInformationByHandle(ptr2, out fileInfo2);

        return ((fileInfo1.FileIndexHigh == fileInfo2.FileIndexHigh) &&
            (fileInfo1.FileIndexLow == fileInfo2.FileIndexLow));
    }
}
  • 2
    Это не использование методов расширения. Это просто статический класс.
  • 1
    Чтобы изменить метод расширения: static public bool CompareFiles (строка path1, строка path2) на static public bool IsSameFileAs (эта строка path1, строка path2); затем используйте как: if (file1.IsSameFileAs (file2)
Показать ещё 3 комментария
5

Здесь растровое расширение, которое может преобразовывать растровые изображения в оттенки серого,

public static Bitmap GrayScale(this Bitmap bitmap)
{
    Bitmap newBitmap = new Bitmap(bitmap.Width, bitmap.Height);
    Graphics g = Graphics.FromImage(newBitmap);

    //the grayscale ColorMatrix
    ColorMatrix colorMatrix = new ColorMatrix(new float[][] {
            new float[] {.3f, .3f, .3f, 0, 0},
            new float[] {.59f, .59f, .59f, 0, 0},
            new float[] {.11f, .11f, .11f, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {0, 0, 0, 0, 1}
    });

    ImageAttributes attributes = new ImageAttributes();
    attributes.SetColorMatrix(colorMatrix);
    g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, attributes);
    g.Dispose();
    return newBitmap;
}

Использование образца:

Bitmap grayscaled = bitmap.GrayScale()
  • 0
    Хороший! Знаете ли вы, как сделать то же самое с WPF (не используя GDI)?
  • 0
    Никогда еще не пробовал с WPF.
5

Здесь другая пара, которую я нашел бесконечно для:

public static T ObjectWithMin<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> predicate)
    where T : class
    where TResult : IComparable
{
    if (!sequence.Any()) return null;

    //get the first object with its predicate value
    var seed = sequence.Select(x => new {Object = x, Value = predicate(x)}).FirstOrDefault();
    //compare against all others, replacing the accumulator with the lesser value
    //tie goes to first object found
    return
        sequence.Select(x => new {Object = x, Value = predicate(x)})
            .Aggregate(seed,(acc, x) => acc.Value.CompareTo(x.Value) <= 0 ? acc : x).Object;
}

public static T ObjectWithMax<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> predicate)
    where T : class
    where TResult : IComparable
{
    if (!sequence.Any()) return null;

    //get the first object with its predicate value
    var seed = sequence.Select(x => new {Object = x, Value = predicate(x)}).FirstOrDefault();
    //compare against all others, replacing the accumulator with the greater value
    //tie goes to last object found
    return
        sequence.Select(x => new {Object = x, Value = predicate(x)})
            .Aggregate(seed, (acc, x) => acc.Value.CompareTo(x.Value) > 0 ? acc : x).Object;
}

Использование:

var myObject = myList.ObjectWithMin(x=>x.PropA);

Эти методы в основном заменяют использование, например

var myObject = myList.OrderBy(x=>x.PropA).FirstOrDefault(); //O(nlog(n)) and unstable

и

var myObject = myList.Where(x=>x.PropA == myList.Min(x=>x.PropA)).FirstOrDefault(); //O(N^2) but stable

и

var minValue = myList.Min(x=>x.PropA);
var myObject = myList.Where(x=>x.PropA == minValue).FirstOrDefault(); //not a one-liner, and though linear and stable it slower (evaluates the enumerable twice)
5

Здесь весело от нашей кодовой базы на работе. Пройдите дорогостоящую ленивую эвалью, перечислимую на рабочем месте, и отбросьте результаты обратно через наблюдаемые.

public static IObservable<T> ToAsyncObservable<T>(this IEnumerable<T> @this)
{
    return Observable.Create<T>(observer =>
    {
        var task = new Task(() =>
        {
            try
            {
                @this.Run(observer.OnNext);
                observer.OnCompleted();
            }
            catch (Exception e)
            {
                observer.OnError(e);
            }
        });

        task.Start();

        return () => { };
    });
}

Глупый образец:

new DirectoryInfo(@"c:\program files")
    .EnumerateFiles("*", SearchOption.AllDirectories)
    .ToAsyncObservable()
    .BufferWithTime(TimeSpan.FromSeconds(0.5))
    .ObserveOnDispatcher()
    .Subscribe(
        l => Console.WriteLine("{0} received", l.Count),
        () => Console.WriteLine("Done!"));

for (;;)
{
    Thread.Sleep(10);
    Dispatcher.PushFrame(new DispatcherFrame());
}

Очевидно, что это расширение будет бесполезно для вас, если вы не используете блестящие реактивные расширения!

ОБНОВЛЕНИЕ, благодаря Ричарду в комментариях, этот метод расширения не нужен. RX уже имеет метод расширения "ToObservable", который принимает IScheduler. Используйте это вместо этого!

  • 0
    Не уверен, что я думаю об использовании @this в качестве имени параметра. С одной стороны, поскольку это метод расширения, вы можете думать о нем как о обычном методе класса. С другой стороны, использование (общего) ключевого слова в качестве имени параметра натирает меня неправильно. Звучит интересно, хотя.
  • 0
    Первоначально я взял @this где-то в блоге или, может быть, здесь, на SO. Изначально у меня были те же опасения, но я использовал его для всех моих методов расширения в течение последних нескольких недель и мне это очень понравилось. Я думаю, что «может воспринимать это как обычный метод класса» значительно перевешивает беспокойство по поводу повторного использования ключевого слова. Я действительно думал об использовании «th» или «self» для имен, но мне особенно нравится, как действительно выскакивает @. Это постоянно напоминает мне, в каком методе я нахожусь.
Показать ещё 4 комментария
5

Вы, наверное, уже знаете, что интересное использование методов расширения - это вид mixin. Некоторые методы расширения, такие как XmlSerializable, загрязняют почти каждый класс; и это не имеет смысла для большинства из них, таких как Thread и SqlConnection.

Некоторые функции должны быть явно смешаны с классами, которые хотят его использовать. Я предлагаю новую нотацию для этого типа с префиксом M.

Затем XmlSerializable:

public interface MXmlSerializable { }
public static class XmlSerializable {
  public static string ToXml(this MXmlSerializable self) {
    if (self == null) throw new ArgumentNullException();
    var serializer = new XmlSerializer(self.GetType());
    using (var writer = new StringWriter()) {
      serializer.Serialize(writer, self);
      return writer.GetStringBuilder().ToString();
    }
  }
  public static T FromXml<T>(string xml) where T : MXmlSerializable {
    var serializer = new XmlSerializer(typeof(T));
    return (T)serializer.Deserialize(new StringReader(xml));
  }
}

Затем класс смешивается в:

public class Customer : MXmlSerializable {
  public string Name { get; set; }
  public bool Preferred { get; set; }
}

И использование просто:

var customer = new Customer { 
  Name = "Guybrush Threepwood", 
  Preferred = true };
var xml = customer.ToXml();

Если вам нравится эта идея, вы можете создать новое пространство имен для полезных миксинов в проекте. Как вы думаете?

О, и, кстати, я думаю, что большинство методов расширения должны явно проверить значение null.

5

Простой, но приятнее, чем "Enumerable.Range", ИМХО:

/// <summary>
/// Replace "Enumerable.Range(n)" with "n.Range()":
/// </summary>
/// <param name="n">iterations</param>
/// <returns>0..n-1</returns>
public static IEnumerable<int> Range(this int n)
{
    for (int i = 0; i < n; i++)
        yield return i;
}
5
static string Format( this string str,
                    , params Expression<Func<string,object>>[] args)
{
    var parameters = args.ToDictionary
                        ( e=>string.Format("{{{0}}}",e.Parameters[0].Name)
                        , e=>e.Compile()(e.Parameters[0].Name));

    var sb = new StringBuilder(str);
    foreach(var kv in parameters)
    {
        sb.Replace( kv.Key
                  , kv.Value != null ? kv.Value.ToString() : "");
    }

    return sb.ToString();
}

С вышеуказанным расширением вы можете написать это:

var str = "{foo} {bar} {baz}".Format(foo=>foo, bar=>2, baz=>new object());

и вы получите "foo 2 System.Object ".

  • 2
    Производительность ужасна с Compile ().
  • 0
    Для чего я использую это (веб-интерфейсы) это приемлемо.
Показать ещё 1 комментарий
4

Я создал приятное Каждое расширение, которое имеет такое же поведение, как и каждая функция jQuery.

Он позволяет что-то вроде ниже, где вы можете получить индекс текущего значения и выйти из цикла, вернув false:

new[] { "first", "second", "third" }.Each((value, index) =>
{
    if (value.Contains("d"))
        return false;
    Console.Write(value);
    return true;
});

Здесь код

/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion.  A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value in the sequence. 
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Action<T> action)
{
    return source.Each((value, index) =>
    {
        action(value);
        return true;
    });
}


/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion.  A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value and its index in the sequence.  
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Action<T, int> action)
{
    return source.Each((value, index) =>
    {
        action(value, index);
        return true;
    });
}

/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion.  A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value in the sequence.  Returns a value indicating whether the iteration should continue.  So return false if you don't want to iterate anymore.</param>
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Func<T, bool> action)
{
    return source.Each((value, index) =>
    {
        return action(value);
    });
}

/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion.  A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value and its index in the sequence.  Returns a value indicating whether the iteration should continue.  So return false if you don't want to iterate anymore.</param>
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Func<T, int, bool> action)
{
    if (source == null)
        return source;

    int index = 0;
    foreach (var sourceItem in source)
    {
        if (!action(sourceItem, index))
            break;
        index++;
    }
    return source;
}
  • 0
    Чем он отличается от TakeWhile? (кроме перегрузок с действием)
4

Я на самом деле просто blogged сегодня. Это сильно типизированная реактивная оболочка вокруг свойства INotifyPropertyChanged.

GetPropertyValues возвращает значения IObservable<T> значений при их изменении, начиная с текущего значения. Если игнорировать текущее значение, вы можете просто вызвать Skip(1) в результате.

Использование выглядит так:

IObservable<int> values = viewModel.GetPropertyValues(x => x.IntProperty);

Реализация:

public static class NotifyPropertyChangeReactiveExtensions
{
    // Returns the values of property (an Expression) as they change, 
    // starting with the current value
    public static IObservable<TValue> GetPropertyValues<TSource, TValue>(
        this TSource source, Expression<Func<TSource, TValue>> property)
        where TSource : INotifyPropertyChanged
    {
        MemberExpression memberExpression = property.Body as MemberExpression;

        if (memberExpression == null)
        {
            throw new ArgumentException(
                "property must directly access a property of the source");
        }

        string propertyName = memberExpression.Member.Name;

        Func<TSource, TValue> accessor = property.Compile();

        return source.GetPropertyChangedEvents()
            .Where(x => x.EventArgs.PropertyName == propertyName)
            .Select(x => accessor(source))
            .StartWith(accessor(source));
    }

    // This is a wrapper around FromEvent(PropertyChanged)
    public static IObservable<IEvent<PropertyChangedEventArgs>>
        GetPropertyChangedEvents(this INotifyPropertyChanged source)
    {
        return Observable.FromEvent<PropertyChangedEventHandler, 
            PropertyChangedEventArgs>(
            h => new PropertyChangedEventHandler(h),
            h => source.PropertyChanged += h,
            h => source.PropertyChanged -= h);
    }
}
4

Эти методы расширения вызывают событие асинхронно. Они были вдохновлены https://stackoverflow.com/questions/1916095/how-do-i-make-an-eventhandler-run-asynchronously.

/// <summary>
/// Invoke an event asynchronously. Each subscriber to the event will be invoked on a separate thread.
/// </summary>
/// <param name="someEvent">The event to be invoked asynchronously.</param>
/// <param name="sender">The sender of the event.</param>
/// <param name="args">The args of the event.</param>
/// <typeparam name="TEventArgs">The type of <see cref="EventArgs"/> to be used with the event.</typeparam>
public static void InvokeAsync<TEventArgs>(this EventHandler<TEventArgs> someEvent, object sender, TEventArgs args)
    where TEventArgs : EventArgs
{
    if (someEvent == null)
    {
        return;
    }

    var eventListeners = someEvent.GetInvocationList();

    AsyncCallback endAsyncCallback = delegate(IAsyncResult iar)
    {
        var ar = iar as AsyncResult;
        if (ar == null)
        {
            return;
        }

        var invokedMethod = ar.AsyncDelegate as EventHandler<TEventArgs>;
        if (invokedMethod != null)
        {
            invokedMethod.EndInvoke(iar);
        }
    };

    foreach (EventHandler<TEventArgs> methodToInvoke in eventListeners)
    {
        methodToInvoke.BeginInvoke(sender, args, endAsyncCallback, null);
    }
}

/// <summary>
/// Invoke an event asynchronously. Each subscriber to the event will be invoked on a separate thread.
/// </summary>
/// <param name="someEvent">The event to be invoked asynchronously.</param>
/// <param name="sender">The sender of the event.</param>
/// <param name="args">The args of the event.</param>
public static void InvokeAsync(this EventHandler someEvent, object sender, EventArgs args)
{
    if (someEvent == null)
    {
        return;
    }

    var eventListeners = someEvent.GetInvocationList();

    AsyncCallback endAsyncCallback = delegate(IAsyncResult iar)
    {
        var ar = iar as AsyncResult;
        if (ar == null)
        {
            return;
        }

        var invokedMethod = ar.AsyncDelegate as EventHandler;
        if (invokedMethod != null)
        {
            invokedMethod.EndInvoke(iar);
        }
    };

    foreach (EventHandler methodToInvoke in eventListeners)
    {
        methodToInvoke.BeginInvoke(sender, args, endAsyncCallback, null);
    }
}

Для использования:

public class Foo
{
    public event EventHandler<EventArgs> Bar;

    public void OnBar()
    {
        Bar.InvokeAsync(this, EventArgs.Empty);
    }
}

Обратите внимание на добавленную выгоду, которую вам не нужно проверять на наличие нуля в событии перед его вызовом. например:.

EventHandler<EventArgs> handler = Bar;
if (handler != null)
{
    // Invoke the event
}

Чтобы проверить:

void Main()
{
    EventHandler<EventArgs> handler1 =
    delegate(object sender, EventArgs args)
    {
        // Simulate performing work in handler1
        Thread.Sleep(100);
        Console.WriteLine("Handled 1");
    };

    EventHandler<EventArgs> handler2 =
    delegate(object sender, EventArgs args)
    {
        // Simulate performing work in handler2
        Thread.Sleep(50);
        Console.WriteLine("Handled 2");
    };

    EventHandler<EventArgs> handler3 =
    delegate(object sender, EventArgs args)
    {
        // Simulate performing work in handler3
        Thread.Sleep(25);
        Console.WriteLine("Handled 3");
    };

    var foo = new Foo();
    foo.Bar += handler1;
    foo.Bar += handler2;
    foo.Bar += handler3;
    foo.OnBar();

    Console.WriteLine("Start executing important stuff");

    // Simulate performing some important stuff here, where we don't want to
    // wait around for the event handlers to finish executing
    Thread.Sleep(1000);

    Console.WriteLine("Finished executing important stuff");
}

Вызов события (обычно) даст этот результат:

Начните выполнять важные вещи
Обработано 3
Обработано 2
Обработано 1
Закончено выполнение важных вещей

Если событие было вызвано синхронно, оно всегда выдавало бы этот результат - и задерживало выполнение "важного" материала:

Обработано 1
Обработано 2
Обработано 3
Начать выполнение важных вещей
Закончено выполнение важных вещей

4

Преобразует список в datatable

public static class DataTableConverter
{
    /// <summary>
    /// Convert a List{T} to a DataTable.
    /// </summary>
    public static DataTable ToDataTable<T>(this IList<T> items)
    {
        var tb = new DataTable(typeof(T).Name);

        PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (PropertyInfo prop in props)
        {
            Type t = GetCoreType(prop.PropertyType);
            tb.Columns.Add(prop.Name, t);
        }

        foreach (T item in items)
        {
            var values = new object[props.Length];

            for (int i = 0; i < props.Length; i++)
            {
                values[i] = props[i].GetValue(item, null);
            }

            tb.Rows.Add(values);
        }

        return tb;
    }

    /// <summary>
    /// Determine of specified type is nullable
    /// </summary>
    public static bool IsNullable(Type t)
    {
        return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
    }

    /// <summary>
    /// Return underlying type if type is Nullable otherwise return the type
    /// </summary>
    public static Type GetCoreType(Type t)
    {
        if (t != null && IsNullable(t))
        {
            if (!t.IsValueType)
            {
                return t;
            }
            else
            {
                return Nullable.GetUnderlyingType(t);
            }
        }
        else
        {
            return t;
        }
    }
}

Использование:

    IList<MyClass> myClassList = new List<MyClass>();
    DataTable myClassDataTable = myClassList.ToDataTable();
  • 1
    И обратное уже включено в .NET как встроенный метод расширения (да, это звучит странно, встроенный метод расширения): stackoverflow.com/questions/208532/…
4

Мое предложение:

public static bool IsNullOrEmpty(this ICollection obj)
{
  return (obj == null || obj.Count == 0);
}

Работает с коллекциями и массивами:

bool isNullOrEmpty = array.IsNullOrEmpty()

вместо

bool isNullOrEmpty = array == null || array.Length == 0;
  • 0
    Как насчет использования IEnumerable вместо ICollection и Any () вместо Count?
  • 0
    @brickner IEnumerable <T> .Any () - только универсальный IEnumerable <T> имеет Any ().
4

Я считаю, что следующий метод расширения весьма полезен:

public static T GetService<T>(this IServiceProvider provider)
{
    return (T)provider.GetService(typeof(T));
}

Это упрощает использование интерфейса IServiceProvider. Для сравнения:

IProvideValueTarget target = (IProvideValueTarget)serviceProvider(typeof(IProvideValueTarget));

и

var target = serviceProvider.GetService<IProvideValueTarget>();
4

String.As<T>, который может быть использован для преобразования строкового значения в качестве некоторого типа (предназначенного для использования в основном с примитивами и типами, поддерживающими IConvertable). Отлично работает с типами Nullable и даже Enums!

public static partial class StringExtensions
{
    /// <summary>
    /// Converts the string to the specified type, using the default value configured for the type.
    /// </summary>
    /// <typeparam name="T">Type the string will be converted to. The type must implement IConvertable.</typeparam>
    /// <param name="original">The original string.</param>
    /// <returns>The converted value.</returns>
    public static T As<T>(this String original)
    {
        return As(original, CultureInfo.CurrentCulture,
                  default(T));
    }

    /// <summary>
    /// Converts the string to the specified type, using the default value configured for the type.
    /// </summary>
    /// <typeparam name="T">Type the string will be converted to.</typeparam>
    /// <param name="original">The original string.</param>
    /// <param name="defaultValue">The default value to use in case the original string is null or empty, or can't be converted.</param>
    /// <returns>The converted value.</returns>
    public static T As<T>(this String original, T defaultValue)
    {
        return As(original, CultureInfo.CurrentCulture, defaultValue);
    }

    /// <summary>
    /// Converts the string to the specified type, using the default value configured for the type.
    /// </summary>
    /// <typeparam name="T">Type the string will be converted to.</typeparam>
    /// <param name="original">The original string.</param>
    /// <param name="provider">Format provider used during the type conversion.</param>
    /// <returns>The converted value.</returns>
    public static T As<T>(this String original, IFormatProvider provider)
    {
        return As(original, provider, default(T));
    }

    /// <summary>
    /// Converts the string to the specified type.
    /// </summary>
    /// <typeparam name="T">Type the string will be converted to.</typeparam>
    /// <param name="original">The original string.</param>
    /// <param name="provider">Format provider used during the type conversion.</param>
    /// <param name="defaultValue">The default value to use in case the original string is null or empty, or can't be converted.</param>
    /// <returns>The converted value.</returns>
    /// <remarks>
    /// If an error occurs while converting the specified value to the requested type, the exception is caught and the default is returned. It is strongly recommended you
    /// do NOT use this method if it is important that conversion failures are not swallowed up.
    ///
    /// This method is intended to be used to convert string values to primatives, not for parsing, converting, or deserializing complex types.
    /// </remarks>
    public static T As<T>(this String original, IFormatProvider provider,
                          T defaultValue)
    {
        T result;
        Type type = typeof (T);

        if (String.IsNullOrEmpty(original)) result = defaultValue;
        else
        {
            // need to get the underlying type if T is Nullable<>.

            if (type.IsNullableType())
            {
                type = Nullable.GetUnderlyingType(type);
            }

            try
            {
                // ChangeType doesn't work properly on Enums
                result = type.IsEnum
                             ? (T) Enum.Parse(type, original, true)
                             : (T) Convert.ChangeType(original, type, provider);
            }
            catch // HACK: what can we do to minimize or avoid raising exceptions as part of normal operation? custom string parsing (regex?) for well-known types? it would be best to know if you can convert to the desired type before you attempt to do so.
            {
                result = defaultValue;
            }
        }

        return result;
    }
}

Это зависит от другого простого расширения для Type:

/// <summary>
/// Extension methods for <see cref="Type"/>.
/// </summary>
public static class TypeExtensions
{
    /// <summary>
    /// Returns whether or not the specified type is <see cref="Nullable{T}"/>.
    /// </summary>
    /// <param name="type">A <see cref="Type"/>.</param>
    /// <returns>True if the specified type is <see cref="Nullable{T}"/>; otherwise, false.</returns>
    /// <remarks>Use <see cref="Nullable.GetUnderlyingType"/> to access the underlying type.</remarks>
    public static bool IsNullableType(this Type type)
    {
        if (type == null) throw new ArgumentNullException("type");

        return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof (Nullable<>));
    }
}

Использование:

var someInt = "1".As<int>();
var someIntDefault = "bad value".As(1); // "bad value" won't convert, so the default value 1 is returned.
var someEnum = "Sunday".As<DayOfWeek>();
someEnum = "0".As<DayOfWeek>(); // returns Sunday
var someNullableEnum = "".As<DayOfWeek?>(null); // returns a null value since "" can't be converted
4

Я не хотел добавлять ничего, что уже было сказано, вот некоторые из них, которые я использую, не упоминались. (Извините, если он слишком длинный):

public static class MyExtensions
{
    public static bool IsInteger(this string input)
    {
        int temp;

        return int.TryParse(input, out temp);
    }

    public static bool IsDecimal(this string input)
    {
        decimal temp;

        return decimal.TryParse(input, out temp);
    }

    public static int ToInteger(this string input, int defaultValue)
    {
        int temp;

        return (int.TryParse(input, out temp)) ? temp : defaultValue;
    }

    public static decimal ToDecimal(this string input, decimal defaultValue)
    {
        decimal temp;

        return (decimal.TryParse(input, out temp)) ? temp : defaultValue;
    }

    public static DateTime ToFirstOfTheMonth(this DateTime input)
    {
        return input.Date.AddDays(-1 * input.Day + 1);
    }

    // Intentionally returns 0 if the target date is before the input date.
    public static int MonthsUntil(this DateTime input, DateTime targetDate)
    {
        input = input.ToFirstOfTheMonth();

        targetDate = targetDate.ToFirstOfTheMonth();

        int result = 0;

        while (input < targetDate)
        {
        input = input.AddMonths(1);
            result++;
        }

        return result;
    }

    // Used for backwards compatibility in a system built before my time.
    public static DataTable ToDataTable(this IEnumerable input)
    {
        // too much code to show here right now...
    }
}
3

Два расширения цвета, которые я использую, в основном для разработки управления:

public static class ColorExtensions
{
  // Gets a color that will be readable on top of a given background color
  public static Color GetForegroundColor(this Color input)
  {
    // Math taken from one of the replies to
    // http://stackoverflow.com/questions/2241447/make-foregroundcolor-black-or-white-depending-on-background
    if (Math.Sqrt(input.R * input.R * .241 + input.G * input.G * .691 + input.B * input.B * .068) > 128)
      return Color.Black;
    else
      return Color.White;
  }

  // Converts a given Color to gray
  public static Color ToGray(this Color input)
  {
    int g = (int)(input.R * .299) + (int)(input.G * .587) + (int)(input.B * .114);
    return Color.FromArgb(input.A, g, g, g);
  }
}

Использование:

Color foreColor = someBackColor.GetForegroundColor();
Color grayColor = someBackColor.ToGray();
3

Не проверял весь поток, поэтому он уже может быть здесь, но:

public static class FluentOrderingExtensions
    public class FluentOrderer<T> : IEnumerable<T>
    {
        internal List<Comparison<T>> Comparers = new List<Comparison<T>>();

        internal IEnumerable<T> Source;

        public FluentOrderer(IEnumerable<T> source)
        {
            Source = source;
        }

        #region Implementation of IEnumerable

        public IEnumerator<T> GetEnumerator()
        {
            var workingArray = Source.ToArray();
            Array.Sort(workingArray, IterativeComparison);

            foreach(var element in workingArray) yield return element;
        }

        private int IterativeComparison(T a, T b)
        {
            foreach (var comparer in Comparers)
            {
                var result = comparer(a,b);
                if(result != 0) return result;
            }
            return 0;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }

    public static FluentOrderer<T> OrderFluentlyBy<T,TResult>(this IEnumerable<T> source, Func<T,TResult> predicate) 
        where TResult : IComparable<TResult>
    {
        var result = new FluentOrderer<T>(source);
        result.Comparers.Add((a,b)=>predicate(a).CompareTo(predicate(b)));
        return result;
    }

    public static FluentOrderer<T> OrderFluentlyByDescending<T,TResult>(this IEnumerable<T> source, Func<T,TResult> predicate) 
        where TResult : IComparable<TResult>
    {
        var result = new FluentOrderer<T>(source);
        result.Comparers.Add((a,b)=>predicate(a).CompareTo(predicate(b)) * -1);
        return result;
    }

    public static FluentOrderer<T> ThenBy<T, TResult>(this FluentOrderer<T> source, Func<T, TResult> predicate)
        where TResult : IComparable<TResult>
    {
        source.Comparers.Add((a, b) => predicate(a).CompareTo(predicate(b)));
        return source;
    }

    public static FluentOrderer<T> ThenByDescending<T, TResult>(this FluentOrderer<T> source, Func<T, TResult> predicate)
        where TResult : IComparable<TResult>
    {
        source.Comparers.Add((a, b) => predicate(a).CompareTo(predicate(b)) * -1);
        return source;
    }
}

Использование:

var myFluentlyOrderedList = GetABunchOfComplexObjects()
    .OrderFluentlyBy(x=>x.PropertyA)
    .ThenByDescending(x=>x.PropertyB)
    .ThenBy(x=>x.SomeMethod())
    .ThenBy(x=>SomeOtherMethodAppliedTo(x))
    .ToList();

... предполагая, конечно, что все предикаты возвращают типы, которые являются IComparable для себя. Он будет работать лучше со стабильным типом, например MergeSort, вместо встроенного QuickSort.NET, но он обеспечивает читаемую способность многопользовательского упорядочения, аналогичную SQL (как можно ближе к цепочке методов). Вы можете расширить это, чтобы разместить участников, которые не являются IComparable, определяя перегрузки, которые берут сравнительную лямбду вместо ее создания на основе предиката.

EDIT: небольшое объяснение, поскольку комментатор получил некоторые всплывающие подсказки: этот набор методов улучшает базовые функции OrderBy(), позволяя сортировать на основе нескольких полей в порядке убывания важности. Пример в реальном мире будет сортировать список счетов-фактур клиентом, а затем номер счета-фактуры (или дату счета-фактуры). Другие методы получения данных в этом порядке либо не будут работать (OrderBy() использует нестабильный тип, поэтому он не может быть привязан) или будет неэффективным, а не похожим на то, что вы пытаетесь сделать.

  • 2
    Как это преимущество по умолчанию OrderBy и OrderByDescending по умолчанию?
  • 0
    OrderBy () не может быть связан; каждый вызов OrderBy () сортируется по одной проекции собранного типа. Вы все равно могли бы заставить его работать, если бы используемый алгоритм сортировки был стабильным, как MergeSort, но встроенный помощник сортировки является нестабильной QuickSort, поэтому нет гарантии поддержания относительного порядка при сортировке по равным условиям. Цепочка OrderBy () также запускает функцию O (nlogn) один раз для каждого OrderBy (); этот набор методов сортирует один раз независимо от того, сколько терминов вы сравниваете.
Показать ещё 4 комментария
3

Было бы здорово иметь Unix TimeStamp и ISO 8601 отформатированную дату и время. широко используется в веб-сайтах и ​​службах отдыха.

Я использую его в своей библиотеке Facebook. Вы можете найти источник http://github.com/prabirshrestha/FacebookSharp/blob/master/src/FacebookSharp.Core/FacebookUtils/DateUtils.cs

private static readonly DateTime EPOCH = DateTime.SpecifyKind(new DateTime(1970, 1, 1, 0, 0, 0, 0),DateTimeKind.Utc);

public static DateTime FromUnixTimestamp(long timestamp)
{
    return EPOCH.AddSeconds(timestamp);
}

public static long ToUnixTimestamp(DateTime date)
{
    TimeSpan diff = date.ToUniversalTime() - EPOCH;
    return (long)diff.TotalSeconds;
}

public static DateTime FromIso8601FormattedDateTime(string iso8601DateTime){
    return DateTime.ParseExact(iso8601DateTime, "o", System.Globalization.CultureInfo.InvariantCulture);
}

public static string ToIso8601FormattedDateTime(DateTime dateTime)
{
    return dateTime.ToString("o");
}

Невозможно использовать в проекте codeplex.

  • 0
    Я сам писал в основном идентичный код более чем один раз.
  • 0
    Интересно. Но не совсем методы расширения.
3

Сравнение строк подстановочных знаков:

public static bool MatchesWildcard(this string text, string pattern)
{
    int it = 0;
    while (text.CharAt(it) != 0 &&
           pattern.CharAt(it) != '*')
    {
        if (pattern.CharAt(it) != text.CharAt(it) && pattern.CharAt(it) != '?')
            return false;
        it++;
    }

    int cp = 0;
    int mp = 0;
    int ip = it;

    while (text.CharAt(it) != 0)
    {
        if (pattern.CharAt(ip) == '*')
        {
            if (pattern.CharAt(++ip) == 0)
                return true;
            mp = ip;
            cp = it + 1;
        }
        else if (pattern.CharAt(ip) == text.CharAt(it) || pattern.CharAt(ip) == '?')
        {
            ip++;
            it++;
        }
        else
        {
            ip = mp;
            it = cp++;
        }
    }

    while (pattern.CharAt(ip) == '*')
    {
        ip++;
    }
    return pattern.CharAt(ip) == 0;
}

public static char CharAt(this string s, int index)
{
    if (index < s.Length)
        return s[index];
    return '\0';
}

Это прямой перевод кода C из в эту статью, следовательно, метод CharAt, который возвращает 0 для конца строки

if (fileName.MatchesWildcard("*.cs"))
{
    Console.WriteLine("{0} is a C# source file", fileName);
}
  • 0
    отлично. Как раз то, что я ищу :-)
  • 0
    Почему бы просто не использовать Regex?
Показать ещё 1 комментарий
3

Вот единственное расширение, которое я написал, которое я использую регулярно. Это упрощает отправку электронной почты с помощью System.Net.Mail.

public static class MailExtension
{
    // GetEmailCreditial(out strServer) gets credentials from an XML file
    public static void Send(this MailMessage email)
    {
        string strServer = String.Empty;
        NetworkCredential credentials = GetEmailCreditial(out strServer);
        SmtpClient client = new SmtpClient(strServer) { Credentials = credentials };
        client.Send(email);
    }

    public static void Send(this IEnumerable<MailMessage> emails)
    {
        string strServer = String.Empty;
        NetworkCredential credentials = GetEmailCreditial(out strServer);
        SmtpClient client = new SmtpClient(strServer) { Credentials = credentials };
        foreach (MailMessage email in emails)
            client.Send(email);
    }
}

// Example of use: 
new MailMessage("[email protected]","[email protected]","This is an important Subject", "Body goes here").Send();
//Assume email1,email2,email3 are MailMessage objects
new List<MailMessage>(){email1, email2, email}.Send();
3

Во время работы с MVC и с множеством операторов if, где я забочусь только о true или false, и печатать null или string.Empty в другом случае, я придумал:

public static TResult WhenTrue<TResult>(this Boolean value, Func<TResult> expression)
{
    return value ? expression() : default(TResult);
}

public static TResult WhenTrue<TResult>(this Boolean value, TResult content)
{
    return value ? content : default(TResult);
}

public static TResult WhenFalse<TResult>(this Boolean value, Func<TResult> expression)
{
    return !value ? expression() : default(TResult);
}

public static TResult WhenFalse<TResult>(this Boolean value, TResult content)
{
    return !value ? content : default(TResult);
}

Это позволяет мне изменить <%= (someBool) ? "print y" : string.Empty %> на <%= someBool.WhenTrue("print y") %>.

Я использую его только в своих представлениях, где я смешиваю код и HTML, в файлах кода, где написана более длинная версия, яснее IMHO.

3

Метод подстроки в классе строк всегда казался мне неадекватным. Обычно, когда вы выполняете подстроку, вы знаете символ (ы), с которого вы хотите начать, и символы (-ы), где вы хотите закончить. Таким образом, я всегда чувствовал, что нужно указать длину, поскольку второй параметр является глупым. Поэтому я написал свои собственные методы расширения. Один, который принимает startIndex и endIndex. И один, который принимает startText (string) и endText (string), поэтому вы можете просто указать текст, откуда начинать подстроку, и текст для того, где его закончить.

ПРИМЕЧАНИЕ. Я не могу назвать метод Substring как в .NET, потому что моя первая перегрузка использует те же типы параметров, что и одна из перегрузок .NET. Поэтому я назвал их Subsetstring. Не стесняйтесь добавлять в CodePlex...

public static class StringExtensions
{
    /// <summary>
    /// Returns a Subset string starting at the specified start index and ending and the specified end
    /// index.
    /// </summary>
    /// <param name="s">The string to retrieve the subset from.</param>
    /// <param name="startIndex">The specified start index for the subset.</param>
    /// <param name="endIndex">The specified end index for the subset.</param>
    /// <returns>A Subset string starting at the specified start index and ending and the specified end
    /// index.</returns>
    public static string Subsetstring(this string s, int startIndex, int endIndex)
    {
        if (startIndex > endIndex)
        {
            throw new InvalidOperationException("End Index must be after Start Index.");
        }

        if (startIndex < 0)
        {
            throw new InvalidOperationException("Start Index must be a positive number.");
        }

        if(endIndex <0)
        {
            throw new InvalidOperationException("End Index must be a positive number.");
        }

        return s.Substring(startIndex, (endIndex - startIndex));
    }

    /// <summary>
    /// Finds the specified Start Text and the End Text in this string instance, and returns a string
    /// containing all the text starting from startText, to the begining of endText. (endText is not
    /// included.)
    /// </summary>
    /// <param name="s">The string to retrieve the subset from.</param>
    /// <param name="startText">The Start Text to begin the Subset from.</param>
    /// <param name="endText">The End Text to where the Subset goes to.</param>
    /// <param name="ignoreCase">Whether or not to ignore case when comparing startText/endText to the string.</param>
    /// <returns>A string containing all the text starting from startText, to the begining of endText.</returns>
    public static string Subsetstring(this string s, string startText, string endText, bool ignoreCase)
    {
        if (string.IsNullOrEmpty(startText) || string.IsNullOrEmpty(endText))
        {
            throw new ArgumentException("Start Text and End Text cannot be empty.");
        }
        string temp = s;
        if (ignoreCase)
        {
            temp = s.ToUpperInvariant();
            startText = startText.ToUpperInvariant();
            endText = endText.ToUpperInvariant();
        }
        int start = temp.IndexOf(startText);
        int end = temp.IndexOf(endText, start);
        return Subsetstring(s, start, end);
    }
}

Использование:

string s = "This is a tester for my cool extension method!!";
       s = s.Subsetstring("tester", "cool",true);

Результат: "тестер для моего"

3

Я использую их в своих веб-проектах, в основном с MVC. У меня есть несколько из них, написанных для ViewData​​strong > и TempData​​strong >

/// <summary>
/// Checks the Request.QueryString for the specified value and returns it, if none 
/// is found then the default value is returned instead
/// </summary>
public static T QueryValue<T>(this HtmlHelper helper, string param, T defaultValue) {
    object value = HttpContext.Current.Request.QueryString[param] as object;
    if (value == null) { return defaultValue; }
    try {
        return (T)Convert.ChangeType(value, typeof(T));
    } catch (Exception) {
        return defaultValue;
    }
}

Таким образом я могу написать что-то вроде...

<% if (Html.QueryValue("login", false)) { %>
    <div>Welcome Back!</div>

<% } else { %>
    <%-- Render the control or something --%>

<% } %>
  • 0
    Можем ли мы использовать код в проекте codeplex?
  • 0
    Любой может использовать это - Помоги себе
Показать ещё 1 комментарий
3
2

Используется в winforms для заполнения comboBox:

List<MyObject> myObjects = new List<MyObject>() { 
    new MyObject() {Name = "a", Id = 0}, 
    new MyObject() {Name = "b", Id = 1}, 
    new MyObject() {Name = "c", Id = 2} }
comboBox.FillDataSource<MyObject>(myObjects, x => x.Name);

Метод расширения:

/** <summary>Fills the System.Windows.Forms.ComboBox object DataSource with a 
 * list of T objects.</summary>
 * <param name="values">The list of T objects.</param>
 * <param name="displayedValue">A function to apply to each element to get the 
 * display value.</param>
 */
public static void FillDataSource<T>(this ComboBox comboBox, List<T> values,
    Func<T, String> displayedValue) {

    // Create dataTable
    DataTable data = new DataTable();
    data.Columns.Add("ValueMember", typeof(T));
    data.Columns.Add("DisplayMember");

    for (int i = 0; i < values.Count; i++) {
        // For each value/displayed value

        // Create new row with value & displayed value
        DataRow dr = data.NewRow();
        dr["ValueMember"] = values[i];
        dr["DisplayMember"] = displayedValue(values[i]) ?? "";
        // Add row to the dataTable
        data.Rows.Add(dr);
    }

    // Bind datasource to the comboBox
    comboBox.DataSource = data;
    comboBox.ValueMember = "ValueMember";
    comboBox.DisplayMember = "DisplayMember";
}
2

В .NET существует IndexOf и LastIndexOf, которые возвращают индекс первого и последнего совпадений в объекте String. У меня есть метод расширения, чтобы получить индекс n-го вхождения:

public static partial class StringExtensions {

    public static int NthIndexOf(this String str, String match, int occurrence) {
        int i = 1;
        int index = 0;

        while (i <= occurrence && 
            ( index = str.IndexOf(match, index + 1) ) != -1) {

            if (i == occurrence) {
                // Occurrence match found!
                return index;
            }
            i++;
        }

        // Match not found
        return -1;
    }
}
2

Я искал способ внести вклад в сообщество некоторых вещей, которые я разработал.

Вот некоторые расширения FileInfo, которые я нахожу весьма полезными.

/// <summary>
/// Open with default 'open' program
/// </summary>
/// <param name="value"></param>
public static Process Open(this FileInfo value)
{
    if (!value.Exists)
        throw new FileNotFoundException("File doesn't exist");
    Process p = new Process();
    p.StartInfo.FileName = value.FullName;
    p.StartInfo.Verb = "Open";
    p.Start();
    return p;
}

/// <summary>
/// Print the file
/// </summary>
/// <param name="value"></param>
public static void Print(this FileInfo value)
{
    if (!value.Exists)
        throw new FileNotFoundException("File doesn't exist");
    Process p = new Process();
    p.StartInfo.FileName = value.FullName;
    p.StartInfo.Verb = "Print";
    p.Start();
}

/// <summary>
/// Send this file to the Recycle Bin
/// </summary>
/// <exception cref="File doesn't exist" />
/// <param name="value"></param>
public static void Recycle(this FileInfo value)
{        
    value.Recycle(false);
}

/// <summary>
/// Send this file to the Recycle Bin
/// On show, if person refuses to send file to the recycle bin, 
/// exception is thrown or otherwise delete fails
/// </summary>
/// <exception cref="File doesn't exist" />
/// <exception cref="On show, if user refuses, throws exception 'The operation was canceled.'" />
/// <param name="value">File being recycled</param>
/// <param name="showDialog">true to show pop-up</param>
public static void Recycle(this FileInfo value, bool showDialog)
{
    if (!value.Exists)
            throw new FileNotFoundException("File doesn't exist");
    if( showDialog )
        FileSystem.DeleteFile
            (value.FullName, UIOption.AllDialogs, 
            RecycleOption.SendToRecycleBin);
    else
        FileSystem.DeleteFile
            (value.FullName, UIOption.OnlyErrorDialogs, 
            RecycleOption.SendToRecycleBin);
}

Открыть любой файл в любимом редакторе пользователя:

new FileInfo("C:\image.jpg").Open();

Распечатайте любой файл, который операционная система знает, как печатать:

new FileInfo("C:\image.jpg").Print();

Отправить любой файл в корзину:

  • Вы должны включить ссылку Microsoft.VisualBasic
  • используйте using Microsoft.VisualBasic.FileIO;

Пример:

new FileInfo("C:\image.jpg").Recycle();

или

// let user have a chance to cancel send to recycle bin.
new FileInfo("C:\image.jpg").Recycle(true);
  • 0
    Я не знаю, как назвать его Open , но это все еще хорошие дополнения, и я удивлен, что никто не опубликовал их раньше.
2

Здесь другое расширение управления, которое я использовал, хотя я не знаю, было ли оно ранее здесь.

public static class ControlExtensions
{
    public static void DoubleBuffer(this Control control) 
    {
        // http://stackoverflow.com/questions/76993/how-to-double-buffer-net-controls-on-a-form/77233#77233
        // Taxes: Remote Desktop Connection and painting: http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx

        if (System.Windows.Forms.SystemInformation.TerminalServerSession) return;
        System.Reflection.PropertyInfo dbProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        dbProp.SetValue(control, true, null);
    }
}

использование:

this.someControl.DoubleBuffer();
2

Я думал, что видел это где-то раньше, но не мог найти, что он предложил где-нибудь здесь. MS имеет функцию TryGetValue на интерфейсе IDictionary, но возвращает bool и дает значение в параметре out, так что здесь более простая и чистая реализация:

public static TVal GetValueOrDefault<TKey, TVal>(this IDictionary<TKey, TVal> d, TKey key) {
  if (d.ContainsKey(key))
    return d[key];
  return default(TVal);
}
  • 2
    Все TryXxx есть out параметров и bool результат: то есть весь смысл этой модели! Ваш метод должен называться как-то как DefaultGetValue чтобы установить его отдельно от TryGetValue .
  • 1
    @Jeroen Согласен, хотя я бы назвал его GetValueOrDefault чтобы он больше соответствовал другим аналогичным методам, таким как FirstOrDefault
Показать ещё 2 комментария
2

Вот несколько методов, которые я использую, чтобы извлечь отдельные атрибуты немного менее болезненными:

public static T GetAttribute<T>(this ICustomAttributeProvider provider, bool inherit = false, int index = 0) where T : Attribute
{
    return provider.GetAttribute(typeof(T), inherit, index) as T;
}

public static Attribute GetAttribute(this ICustomAttributeProvider provider, Type type, bool inherit = false, int index = 0)
{
    bool exists = provider.IsDefined(type, inherit);
    if (!exists)
    {
        return null;
    }

    object[] attributes = provider.GetCustomAttributes(type, inherit);
    if (attributes != null && attributes.Length != 0)
    {
        return attributes[index] as Attribute;
    }
    else
    {
        return null;
    }
}

Использование (реализация this enum description hack):

public static string GetDescription(this Enum value)
{
    var fieldInfo = value.GetType().GetField(value.ToString());
    var attribute = fieldInfo.GetAttribute<DescriptionAttribute>();
    return attribute != null ? attribute.Description : null;
}

Не забудьте включить это в проект CodePlex!

2

Я написал, как четыре метода расширения, так что вот несколько из них, которые я нашел особенно полезными. Не стесняйтесь реализовывать.

public static class ControlExtenders
{
    /// <summary>
    /// Advanced version of find control.
    /// </summary>
    /// <typeparam name="T">Type of control to find.</typeparam>
    /// <param name="id">Control id to find.</param>
    /// <returns>Control of given type.</returns>
    /// <remarks>
    /// If the control with the given id is not found
    /// a new control instance of the given type is returned.
    /// </remarks>
    public static T FindControl<T>(this Control control, string id) where T : Control
    {
        // User normal FindControl method to get the control
        Control _control = control.FindControl(id);

        // If control was found and is of the correct type we return it
        if (_control != null && _control is T)
        {
            // Return new control
            return (T)_control;
        }

        // Create new control instance
        _control = (T)Activator.CreateInstance(typeof(T));

        // Add control to source control so the
        // next it is found and the value can be
        // passed on itd, remember to hide it and
        // set an ID so it can be found next time
        if (!(_control is ExtenderControlBase))
        {
            _control.Visible = false;
        }
        _control.ID = id;
        control.Controls.Add(_control);

        // Use reflection to create a new instance of the control
        return (T)_control;
    }
}

public static class GenericListExtenders
{
    /// <summary>
    /// Sorts a generic list by items properties.
    /// </summary>
    /// <typeparam name="T">Type of collection.</typeparam>
    /// <param name="list">Generic list.</param>
    /// <param name="fieldName">Field to sort data on.</param>
    /// <param name="sortDirection">Sort direction.</param>
    /// <remarks>
    /// Use this method when a dinamyc sort field is requiered. If the 
    /// sorting field is known manual sorting might improve performance.
    /// </remarks>
    public static void SortObjects<T>(this List<T> list, string fieldName, SortDirection sortDirection)
    {
        PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
        if (propInfo != null)
        {
            Comparison<T> compare = delegate(T a, T b)
            {
                bool asc = sortDirection == SortDirection.Ascending;
                object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
                object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);
                return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
            };
            list.Sort(compare);
        }
    }

    /// <summary>
    /// Creates a pagged collection from generic list.
    /// </summary>
    /// <typeparam name="T">Type of collection.</typeparam>
    /// <param name="list">Generic list.</param>
    /// <param name="sortField">Field to sort data on.</param>
    /// <param name="sortDirection">Sort direction.</param>
    /// <param name="from">Page from item index.</param>
    /// <param name="to">Page to item index.</param>
    /// <param name="copy">Creates a copy and returns a new list instead of changing the current one.</param>
    /// <returns>Pagged list collection.</returns>
    public static List<T> Page<T>(this List<T> list, string sortField, bool sortDirection, int from, int to, bool copy)
    {
        List<T> _pageList = new List<T>();

        // Copy list
        if (copy)
        {
            T[] _arrList = new T[list.Count];
            list.CopyTo(_arrList);
            _pageList = new List<T>(_arrList);
        }
        else
        {
            _pageList = list;
        }

        // Make sure there are enough items in the list
        if (from > _pageList.Count)
        {
            int diff = Math.Abs(from - to);
            from = _pageList.Count - diff;
        }
        if (to > _pageList.Count)
        {
            to = _pageList.Count;
        }

        // Sort items
        if (!string.IsNullOrEmpty(sortField))
        {
            SortDirection sortDir = SortDirection.Descending;
            if (!sortDirection) sortDir = SortDirection.Ascending;
            _pageList.SortObjects(sortField, sortDir);
        }

        // Calculate max number of items per page
        int count = to - from;
        if (from + count > _pageList.Count) count -= (from + count) - _pageList.Count;

        // Get max number of items per page
        T[] pagged = new T[count];
        _pageList.CopyTo(from, pagged, 0, count);

        // Return pagged items
        return new List<T>(pagged);
    }

    /// <summary>
    /// Shuffle list items.
    /// </summary>
    /// <typeparam name="T">List type.</typeparam>
    /// <param name="list">Generic list.</param>
    public static void Shuffle<T>(this List<T> list)
    {
        Random rng = new Random();
        for (int i = list.Count - 1; i > 0; i--)
        {
            int swapIndex = rng.Next(i + 1);
            if (swapIndex != i)
            {
                T tmp = list[swapIndex];
                list[swapIndex] = list[i];
                list[i] = tmp;
            }
        }
    }

    /// <summary>
    /// Converts generic List to DataTable.
    /// </summary>
    /// <typeparam name="T">Type.</typeparam>
    /// <param name="list">Generic list.</param>
    /// <param name="columns">Name of the columns to copy to the DataTable.</param>
    /// <returns>DataTable.</returns>
    public static DataTable ToDataTable<T>(this List<T> list, string[] columns)
    {
        List<string> _columns = new List<string>(columns);
        DataTable dt = new DataTable();

        foreach (PropertyInfo info in typeof(T).GetProperties())
        {
            if (_columns.Contains(info.Name) || columns == null)
            {
                dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
            }
        }
        foreach (T t in list)
        {
            DataRow row = dt.NewRow();
            foreach (PropertyInfo info in typeof(T).GetProperties())
            {
                if (_columns.Contains(info.Name) || columns == null)
                {
                    row[info.Name] = info.GetValue(t, null);
                }
            }
            dt.Rows.Add(row);
        }
        return dt;
    }
}

public static class DateTimeExtenders
{
    /// <summary>
    /// Returns number of month from a string representation.
    /// </summary>
    /// <returns>Number of month.</returns>
    public static int MonthToNumber(this DateTime datetime, string month)
    {
        month = month.ToLower();
        for (int i = 1; i <= 12; i++)
        {
            DateTime _dt = DateTime.Parse("1." + i + ".2000");
            string _month = CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i).ToLower();
            if (_month == month)
            {
                return i;
            }
        }
        return 0;
    }

    /// <summary>
    /// Returns month name from month number.
    /// </summary>
    /// <returns>Name of month.</returns>
    public static string MonthToName(this DateTime datetime, int month)
    {
        for (int i = 1; i <= 12; i++)
        {
            if (i == month)
            {
                return CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i);
            }
        }
        return "";
    }
}

public static class ObjectExtender
{
    public static object CloneBinary<T>(this T originalObject)
    {
        using (var stream = new System.IO.MemoryStream())
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            binaryFormatter.Serialize(stream, originalObject);
            stream.Position = 0;
            return (T)binaryFormatter.Deserialize(stream);
        }
    }

    public static object CloneObject(this object obj)
    {
        using (MemoryStream memStream = new MemoryStream())
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
            binaryFormatter.Serialize(memStream, obj);
            memStream.Position = 0;
            return binaryFormatter.Deserialize(memStream);
        }
    }
}

public static class StringExtenders
{
    /// <summary>
    /// Returns string as unit.
    /// </summary>
    /// <param name="value">Value.</param>
    /// <returns>Unit</returns>
    public static Unit ToUnit(this string value)
    {
        // Return empty unit
        if (string.IsNullOrEmpty(value))
            return Unit.Empty;

        // Trim value
        value = value.Trim();

        // Return pixel unit
        if (value.EndsWith("px"))
        {
            // Set unit type
            string _int = value.Replace("px", "");

            // Try parsing to int
            double _val = 0;
            if (!double.TryParse(_int, out _val))
            {
                // Invalid value
                return Unit.Empty;
            }

            // Return unit
            return new Unit(_val, UnitType.Pixel);
        }

        // Return percent unit
        if (value.EndsWith("%"))
        {
            // Set unit type
            string _int = value.Replace("%", "");

            // Try parsing to int
            double _val = 0;
            if (!double.TryParse(_int, out _val))
            {
                // Invalid value
                return Unit.Empty;
            }

            // Return unit
            return new Unit(_val, UnitType.Percentage);
        }

        // No match found
        return new Unit();
    }

    /// <summary>
    /// Returns alternative string if current string is null or empty.
    /// </summary>
    /// <param name="str"></param>
    /// <param name="alternative"></param>
    /// <returns></returns>
    public static string Alternative(this string str, string alternative)
    {
        if (string.IsNullOrEmpty(str)) return alternative;
        return str;
    }

    /// <summary>
    /// Removes all HTML tags from string.
    /// </summary>
    /// <param name="html">String containing HTML tags.</param>
    /// <returns>String with no HTML tags.</returns>
    public static string StripHTML(this string html)
    {
        string nohtml = Regex.Replace(html, "<(.|\n)*?>", "");
        nohtml = nohtml.Replace("\r\n", "").Replace("\n", "").Replace("&nbsp;", "").Trim();
        return nohtml;
    }
}

Первая из них моя любимая, поскольку она позволяет мне заменить:

Control c = this.FindControl("tbName");
if (c != null)
{
    // Do something with c
    customer.Name = ((TextBox)c).Text;
}

При этом:

TextBox c = this.FindControl<TextBox>("tbName");
customer.Name = c.Text;

Настройки строковых значений по умолчанию:

string str = "";
if (string.IsNullOrEmpty(str))
{
    str = "I'm empty!";
}

становится:

str = str.Alternative("I'm empty!");
2

Для краткого увеличения событий:

public static void Raise(this EventHandler handler, object sender, EventArgs e)
{
    if (handler != null)
    {
        handler(sender, e);
    }
}

public static void Raise<T>(this EventHandler<T> handler, object sender, T e) where T : EventArgs
{
    if (handler != null)
    {
        handler(sender, e);
    }
}

Использование:

public event EventHandler Bar;

public void Foo()
{
    Bar.Raise(this, EventArgs.Empty);
}

Здесь немного обсуждается потенциальные проблемы безопасности потоков здесь. Начиная с .NET 4, приведенная выше форма является потокобезопасной, но требует переупорядочения и некоторых блокировок при использовании более старой версии.

  • 0
    Есть проблема с этим решением: вы можете использовать его, только если событие объявлено в текущем классе, а не если оно объявлено в базовом классе ...
  • 0
    @ Томас: Разве это не верно для ручного вызова событий? Решение состоит в том, чтобы использовать шаблон protected virtual void OnBar(Eventargs e) , описанный здесь: msdn.microsoft.com/en-us/library/hy3sefw3%28VS.80%29.aspx .
Показать ещё 4 комментария
2

Вдохновленный String.IsNullOrEmpty

Чтобы проверить, что данный список является нулевым или пустым

public static bool IsNullOrEmpty<TSource>(this List<TSource> src)
{            
    return (src == null || src.Count == 0);
}

И это нужно для проверки данных 2 файлов и свойств

public static bool Compare(this FileInfo f1, FileInfo f2, string propertyName)
{
    try
    {
        PropertyInfo p1 = f1.GetType().GetProperty(propertyName);
        PropertyInfo p2 = f2.GetType().GetProperty(propertyName);

        if (p1.GetValue(f1, null) == p2.GetValue(f1, null))
            return true;
    }
    catch (Exception ex)
    {
        return false;
    }
    return false;
}

И используйте его вот так

FileInfo fo = new FileInfo("c:\\netlog.txt");
FileInfo f1 = new FileInfo("c:\\regkey.txt");

fo.compare(f1, "CreationTime");
  • 0
    Может быть расширено, чтобы быть более общим, слишком public static bool CompareByProperty<Tself, Tother>(this Tself self, Tother other, string propertyName) но вам придется изменить сравнение, чтобы использовать Equals(value1, value2) вместо == поскольку == сравнивает ссылку для типов объектов: stackoverflow.com/questions/814878/…
  • 0
    ((src == null || src.Count == 0)? true: false) == (src == null || src.Count == 0)
Показать ещё 4 комментария
2

Мое самое используемое расширение - это формат, который может форматировать массивы байтов:

/// <summary>
/// Returns a string representation of a byte array.
/// </summary>
/// <param name="bytearray">The byte array to represent.</param>
/// <param name="subdivision">The number of elements per group,
/// or 0 to not restrict it. The default is 0.</param>
/// <param name="subsubdivision">The number of elements per line,
/// or 0 to not restrict it. The default is 0.</param>
/// <param name="divider">The string dividing the individual bytes. The default is " ".</param>
/// <param name="subdivider">The string dividing the groups. The default is "  ".</param>
/// <param name="subsubdivider">The string dividing the lines. The default is "\r\n".</param>
/// <param name="uppercase">Whether the representation is in uppercase hexadecimal.
/// The default is <see langword="true"/>.</param>
/// <param name="prebyte">The string to put before each byte. The default is an empty string.</param>
/// <param name="postbyte">The string to put after each byte. The default is an empty string.</param>
/// <returns>The string representation.</returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="bytearray"/> is <see langword="null"/>.
/// </exception>
public static string ToArrayString(this byte[] bytearray,
    int subdivision = 0,
    int subsubdivision = 0,
    string divider = " ",
    string subdivider = "  ",
    string subsubdivider = "\r\n",
    bool uppercase = true,
    string prebyte = "",
    string postbyte = "")
{
    #region Contract
    if (bytearray == null)
        throw new ArgumentNullException("bytearray");
    #endregion

    StringBuilder sb = new StringBuilder(
        bytearray.Length * (2 + divider.Length + prebyte.Length + postbyte.Length) +
        (subdivision > 0 ? (bytearray.Length / subdivision) * subdivider.Length : 0) +
        (subsubdivision > 0 ? (bytearray.Length / subsubdivision) * subsubdivider.Length : 0));
    int groupElements = (subdivision > 0 ? subdivision - 1 : -1);
    int lineElements = (subsubdivision > 0 ? subsubdivision - 1 : -1);
    for (long i = 0; i < bytearray.LongLength - 1; i++)
    {
        sb.Append(prebyte);
        sb.Append(String.Format(CultureInfo.InvariantCulture, (uppercase ? "{0:X2}" : "{0:x2}"), bytearray[i]));
        sb.Append(postbyte);

        if (lineElements == 0)
        {
            sb.Append(subsubdivider);
            groupElements = subdivision;
            lineElements = subsubdivision;
        }
        else if (groupElements == 0)
        {
            sb.Append(subdivider);
            groupElements = subdivision;
        }
        else
            sb.Append(divider);

        lineElements--;
        groupElements--;
    }
    sb.Append(prebyte);
    sb.Append(String.Format(CultureInfo.InvariantCulture, (uppercase ? "{0:X2}" : "{0:x2}"), bytearray[bytearray.LongLength - 1]));
    sb.Append(postbyte);

    return sb.ToString();
}

По умолчанию ToArrayString() просто печатает массив байтов как длинную строку отдельных байтов. Однако ToArrayString(4, 16) группирует байты в группах по четыре, с 16 байтами в строке, так же, как и в вашем любимом шестнадцатеричном редакторе. И следующее красиво форматирует массив байтов для использования в коде С#:

byte[] bytearray = new byte[]{ ... };
Console.Write(bytearray.ToArrayString(4, 16, ", ", ",   ", ",\r\n", true, "0x"));

Это было написано мной, поэтому вы можете поставить его на Codeplex.

  • 0
    Ух, 8 параметров (не считая this параметра)! ИМХО, любой метод с более чем 4 параметрами требует рефакторинга ...
2

Я уверен, что это было сделано раньше, но я часто использую этот метод (и более простые производные):

public static bool CompareEx(this string strA, string strB, CultureInfo culture, bool ignoreCase)
{
    return string.Compare(strA, strB, ignoreCase, culture) == 0;
}

Вы можете записать его несколькими способами, но мне это нравится, потому что он очень быстро объединяет мой подход к сравнению строк при сохранении мне строк кода (или символов кода).

2

NullPartial HTML-помощник для ASP MVC.

При передаче нулевой модели HTML.Partial и HTML.RenderPartial предоставят модель View, если этот частичный текст строго типизирован, а вид имеет другой тип, он будет генерировать исключение, а не передавать нулевую ссылку. Эти помощники позволяют указать два разных элементарных элемента, чтобы вы могли оставить свои нулевые тесты в представлении.

У вас есть разрешение включить это на странице Codeplex

public static class nullpartials
    {
        public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model)
        {
            if (Model == null)
                return helper.Partial(NullPartial);
            else
                return helper.Partial(Partial, Model);
        }

        public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model, ViewDataDictionary viewdata)
        {
            if (Model == null)
                return helper.Partial(NullPartial, viewdata);
            else
                return helper.Partial(Partial, Model, viewdata);
        }

        public static void RenderNullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model)
        {
            if (Model == null)
            {
                helper.RenderPartial(NullPartial);
                return;
            }
            else
            {
                helper.RenderPartial(Partial, Model);
                return;
            }
        }

        public static void RenderNullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model, ViewDataDictionary viewdata)
        {
            if (Model == null)
            {
                helper.RenderPartial(NullPartial, viewdata);
                return;
            }
            else
            {
                helper.RenderPartial(Partial, Model, viewdata);
                return;
            }
        }
    }
  • 0
    Это хороший.
2

Я реализовал пакет методов расширения (доступно в http://foop.codeplex.com/), и некоторые из моих ежедневных используемых:

// the most beloved extension method for me is Pipe:
<%= variable.Pipe(x => this.SomeFunction(x)).Pipe(y =>
{
    ...;
    return this.SomeOtherFunction(y);
}) %>

var d = 28.December(2009); // some extension methods for creating DateTime
DateTime justDatePart = d.JustDate();
TimeSpan justTimePart = d.JustTime();
var nextTime = d.Add(5.Hours());

using(StreamReader reader = new StreamReader("lines-of-data-file-for-example")) {
    ...
    // for reading streams line by line and usable in LINQ
    var query = from line in reader.Lines(); 
                where line.Contains(_today)
                select new { Parts = PartsOf(line), Time = _now };
}

500.Sleep();

XmlSerialize and XmlDeserialize

IsNull and IsNotNull

IfTrue, IfFalse and Iff:
true.IfTrue(() => Console.WriteLine("it is true then!");

IfNull and IfNotNull
  • 0
    +1 Мне особенно понравился метод Трубы. Мне пришлось скачать ваш источник, чтобы узнать, что это было похоже на Where для одного значения. Может ли кто-нибудь отредактировать ответ, чтобы прояснить этот момент?
  • 0
    «Труба» отличается от «Где». «Где» - это «карта» (в математическом смысле и на функциональных языках), которая принимает набор (коллекция и в .NET случае IEnumerable <T>) и функцию (которая в .NET земле является делегатом и может быть представлена лямбда-выражением типа x => x> 2. единственное ограничение на предоставляемый предикат состоит в том, что он должен возвращать логическое значение. Оператор 'Pipe' - это распространенный инструмент в функциональных языках. Его основное использование - для цепочки вычислений (вызовов функций). Он получает значение & функцию (например, x => f (x)), затем применяет функцию к значению и возвращает результат.
Показать ещё 1 комментарий
2

Обматывает строку каждые n символов.

public static string WrapAt(this string str, int WrapPos)
{
    if (string.IsNullOrEmpty(str))
        throw new ArgumentNullException("str", "Cannot wrap a null string");
    str = str.Replace("\r", "").Replace("\n", "");

    if (str.Length <= WrapPos)
        return str;

    for (int i = str.Length; i >= 0; i--)
        if (i % WrapPos == 0 && i > 0 && i != str.Length)
            str = str.Insert(i, "\r\n");
    return str;
}
2

Это может быть весьма полезно:

    public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
    {
        if (first == null)
            throw new ArgumentNullException("first");
        if (second == null)
            throw new ArgumentNullException("second");
        if (selector == null)
            throw new ArgumentNullException("selector");

        using (var enum1 = first.GetEnumerator())
        using (var enum2 = second.GetEnumerator())
        {
            while (enum1.MoveNext() && enum2.MoveNext())
            {
                yield return selector(enum1.Current, enum2.Current);
            }
        }
    }

Он добавлен в класс Enumerable в .NET 4.0, но удобнее иметь его в 3.5.

Пример:

var names = new[] { "Joe", "Jane", "Jack", "John" };
var ages = new[] { 42, 22, 18, 33 };

var persons = names.Zip(ages, (n, a) => new { Name = n, Age = a });

foreach (var p in persons)
{
    Console.WriteLine("{0} is {1} years old", p.Name, p.Age);
}
  • 0
    Помните, что валидация аргументов не должна находиться в том же методе, что и yield return . Проблема состоит в том, что ArgumentNullException будут выброшены в начале итерации возвращенного «запроса». Это должно было быть брошено при вызове метода Zip .
2

FindControl со встроенным литьем:

public static T FindControl<T>(this Control control, string id) where T : Control
{
    return (T)control.FindControl(id);
}

Ничего удивительного, но я чувствую, что он делает для более чистого кода.

// With extension method
container.FindControl<TextBox>("myTextBox").SelectedValue = "Hello world!";

// Without extension method
((TextBox)container.FindControl("myTextBox")).SelectedValue = "Hello world!";

Это можно поместить в проект codeplex, если это необходимо

  • 0
    Я предпочел бы использовать в as T вместо кастинга
2

Уменьшает длину строки до toLength и добавляет дополнительную строку в конец сокращенной строки, чтобы обозначить, что строка была сокращена (по умолчанию ...)

public static string Shorten(this string str, int toLength, string cutOffReplacement = " ...")
{
    if (string.IsNullOrEmpty(str) || str.Length <= toLength)
        return str;
    else
        return str.Remove(toLength) + cutOffReplacement;
}
  • 2
    Добавление «...» вернет ShortenToLength + 4 символа, то есть строку длиннее, чем указано в документации.
  • 0
    Этот метод требует некоторых модульных тестов TDD для коротких входов. ;-)
Показать ещё 1 комментарий
2

Два маленьких (некоторые люди считают их глупыми), что я включил все мои проекты:

public static bool IsNull(this object o){
  return o == null;
}

и

public static bool IsNullOrEmpty(this string s){
  return string.IsNullOrEmpty(s);
}

Это делает мой код намного более плавным.

if (myClassInstance.IsNull()) //... do something

if (myString.IsNullOrEmpty()) //... do something

Я думаю, что они сделают действительно приятные свойства расширения; если мы когда-нибудь их получим.

  • 1
    Будет ли это лучше? public static bool IsNull <T> (это T obj), где T: class {return (obj == null); }
  • 0
    @ Дэн Диплом Я не думаю, что твои изменения будут иметь какое-либо значение вообще. Нет никакой разницы в том, чтобы использовать дженерики для сравнения объекта с нулем.
Показать ещё 6 комментариев
2

GetMemberName позволяет получить строку с именем члена с безопасностью времени компиляции.

public static string GetMemberName<T, TResult>(
    this T anyObject, 
    Expression<Func<T, TResult>> expression)
{
    return ((MemberExpression)expression.Body).Member.Name;
}

Использование:

"blah".GetMemberName(x => x.Length); // returns "Length"

Он поставляется вместе с статическим методом без расширения, если у вас нет экземпляра:

public static string GetMemberName<T, TReturn>(
    Expression<Func<T, TReturn>> expression)
    where T : class
{
    return ((MemberExpression)expression.Body).Member.Name;
}

Но вызов выглядит не совсем красиво:

ReflectionUtility.GetMemberName((string) s => s.Length); // returns "Length"

Вы можете поместить его на Codeplex, если хотите.

2

Мне нравятся эти методы для обработки перечислений, у которых есть атрибут Flags:

public static bool AnyOf(this object mask, object flags)
{
    return ((int)mask & (int)flags) != 0;
}
public static bool AllOf(this object mask, object flags)
{
    return ((int)mask & (int)flags) == (int)flags;
}
public static object SetOn(this object mask, object flags)
{
    return (int)mask | (int)flags;
}
etc.

Пример использования:

var options = SomeOptions.OptionA;
options = options.SetOn(OptionB);
options = options.SetOn(OptionC);

if (options.AnyOf(SomeOptions.OptionA | SomeOptions.OptionB))
{
etc.

Исходные методы были из этой статьи: http://www.codeproject.com/KB/cs/masksandflags.aspx?display=Print Я просто преобразовал их в методы расширения.

Одной из проблем с ними является то, что параметры типа объекта, что означает, что все объекты в конечном итоге расширяются этими методами, тогда как в идеале они должны применяться только к перечислениям.

Обновление Согласно комментариям, вы можете обойти "загрязнение подписи" за счет производительности, например:

public static bool AnyOf(this Enum mask, object flags)
{
    return (Convert.ToInt642(mask) & (int)flags) != 0;
}
  • 1
    Проблемы с этими расширениями: * Все объекты расширены (сигнатурное загрязнение) * Затраты на упаковку / распаковку * Не все перечисления являются производными от int, также могут быть байты и long
  • 0
    Хорошие моменты, Ринат. Я хотел бы, чтобы был способ написать эти методы расширения.
Показать ещё 1 комментарий
2

Эти методы расширения довольно полезны для меня при анализе ввода формы перед вводом в базу данных

public static int? ToInt(this string input) 
{
    int val;
    if (int.TryParse(input, out val))
        return val;
    return null;
}

public static DateTime? ToDate(this string input)
{
    DateTime val;
    if (DateTime.TryParse(input, out val))
        return val;
    return null;
}

public static decimal? ToDecimal(this string input)
{
    decimal val;
    if (decimal.TryParse(input, out val))
        return val;
    return null;
}
2

Я использую этот довольно много...

Исходный код:

if (guid != Guid.Empty) return guid;
else return Guid.NewGuid();

Новый код:

return guid.NewGuidIfEmpty();

Метод расширения:

public static Guid NewGuidIfEmpty(this Guid uuid)
{
    return (uuid != Guid.Empty ? uuid : Guid.NewGuid());
}
  • 1
    Я думаю, что это сбивает с толку ...
  • 0
    Может быть что-то вроде ... guid.NewGuidIfEmpty (); возвратный гид; ... может быть лучше, семантически говоря.
2

Пригодится для модульного тестирования:

public static IList<T> Clone<T>(this IList<T> list) where T : ICloneable
{
    var ret = new List<T>(list.Count);
    foreach (var item in list)
        ret.Add((T)item.Clone());

    // done
    return ret;
}

Ряд таких, как TWith2Sugars, альтернативный сокращенный синтаксис:

public static long? ToNullableInt64(this string val)
{
    long ret;
    return Int64.TryParse(val, out ret) ? ret : new long?();
}

И, наконец, это - есть ли что-то уже в BCL, которое делает следующее?

public static void Split<T>(this T[] array, 
    Func<T,bool> determinator, 
    IList<T> onTrue, 
    IList<T> onFalse)
{
    if (onTrue == null)
        onTrue = new List<T>();
    else
        onTrue.Clear();

    if (onFalse == null)
        onFalse = new List<T>();
    else
        onFalse.Clear();

    if (determinator == null)
        return;

    foreach (var item in array)
    {
        if (determinator(item))
            onTrue.Add(item);
        else
            onFalse.Add(item);
    }
}
  • 0
    Вы можете сделать это с помощью двух операторов linq select-where. Это считается как BCL?
  • 0
    Да. (Обязательное ограничение на количество комментариев здесь.)
2

Более простой способ загрузить настройки по умолчанию из коллекции (в реальной жизни я использую его для заполнения настроек из любого источника, включая командную строку, параметры URL ClickOnce и т.д.):

public static void LoadFrom(this ApplicationSettingsBase settings, NameValueCollection configuration)
{
    if (configuration != null)
        foreach (string key in configuration.AllKeys)
            if (!String.IsNullOrEmpty(key))
                try
                {
                    settings[key] = configuration.Get(key);
                }
                catch (SettingsPropertyNotFoundException)
                {
                  // handle bad arguments as you wish
                }
}

Пример:

Settings.Default.LoadFrom(new NameValueCollection() { { "Setting1", "Value1" }, { "Setting2", "Value2" } });
  • 0
    Хм, что именно было не так с этим? Я не против понизить голос, но я честно хотел бы знать, не должен ли он работать или что-то.
1

Я еще не видел ответа с этим...

public static string[] Split(this string value, string regexPattern)
{
    return value.Split(regexPattern, RegexOptions.None);
}

public static string[] Split(this string value, string regexPattern, 
    RegexOptions options)
{
    return Regex.Split(value, regexPattern, options);
}

Использование:

var obj = "test1,test2,test3";
string[] arrays = obj.Split(",");
1

Иногда необходимо иметь экземпляр класса независимо от того, действителен ли он, но не null

public static T Safe<T>(this T obj) where T : new()
{
    if (obj == null)
    {
        obj = new T();
    }

    return obj;
}
Использование

будет выглядеть следующим образом:

MyClass myClass = Provider.GetSomeResult();
string temp = myClass.Safe().SomeValue;

вместо:

MyClass myClass = Provider.GetSomeResult();
string temp = "some default value";
if (myClass != null)
{
        temp = myClass.SomeValue;
}

Извините, если это двуличие, но я его не нахожу.

1

Используйте рефлексию, чтобы найти метод TryParse и вызывать его на целевой строке. Необязательный параметр указывает, что должно быть возвращено, если преобразование завершается с ошибкой. Я нахожу этот метод весьма полезным, большую часть времени. Хорошо известно о параметре Convert.ChangeType, но я нахожу это более полезным, что при использовании результата по умолчанию и много чего. Обратите внимание, что найденные методы хранятся в словаре, хотя я подозреваю, что бокс в конечном итоге замедляет это.

Этот метод является моим любимым, потому что он на законных основаниях использует множество языковых функций.

private static readonly Dictionary<Type, MethodInfo> Parsers = new Dictionary<Type, MethodInfo>();

public static T Parse<T>(this string value, T defaultValue = default(T))
{
    if (string.IsNullOrEmpty(value)) return defaultValue;

    if (!Parsers.ContainsKey(typeof(T)))
        Parsers[typeof (T)] = typeof (T).GetMethods(BindingFlags.Public | BindingFlags.Static)
            .Where(mi => mi.Name == "TryParse")
            .Single(mi =>
                        {
                            var parameters = mi.GetParameters();
                            if (parameters.Length != 2) return false;
                            return parameters[0].ParameterType == typeof (string) &&
                                   parameters[1].ParameterType == typeof (T).MakeByRefType();
                        });

    var @params = new object[] {value, default(T)};
    return (bool) Parsers[typeof (T)].Invoke(null, @params) ?
        (T) @params[1] : defaultValue;
}

Использование:

var hundredTwentyThree = "123".Parse(0);
var badnumber = "test".Parse(-1);
var date = "01/01/01".Parse<DateTime>();
  • 0
    Даже если вы кэшируете MethodInfo в словаре, вызывая MethodInfo.Invoke все еще очень медленно ... вы должны вместо этого создавать и кэшировать динамически создаваемых делегатов.
1

Некоторые инструменты для IEnumerable: ToString (Format), ToString (Function) и Join (Separator).

Например:

var names = new[] { "Wagner", "Francine", "Arthur", "Bernardo" };

names.ToString("Name: {0}\n");
// Name: Wagner
// Name: Francine
// Name: Arthur
// Name: Bernardo

names.ToString(name => name.Length > 6 ? String.Format("{0} ", name) : String.Empty);
// Francine Bernardo

names.Join(" - ");
// Wagner - Francine - Arthur - Bernardo

Расширения:

public static string ToString<T>(this IEnumerable<T> self, string format)
{
    return self.ToString(i => String.Format(format, i));
}

public static string ToString<T>(this IEnumerable<T> self, Func<T, object> function)
{
    var result = new StringBuilder();

    foreach (var item in self) result.Append(function(item));

    return result.ToString();
}

public static string Join<T>(this IEnumerable<T> self, string separator)
{
    return String.Join(separator, values: self.ToArray());
}
  • 0
    Вы можете заменить все в вашем методе Join<T> следующим образом: return string.Join(seperator, self.ToArray()) .
  • 0
    О, действительно, я забыл этот метод. Спасибо, Пондидум! Ред.
1

Нормализация пробелов весьма полезна, особенно при работе с пользовательским вводом:

namespace Extensions.String
{
    using System.Text.RegularExpressions;

    public static class Extensions
    {
        /// <summary>
        /// Normalizes whitespace in a string.
        /// Leading/Trailing whitespace is eliminated and
        /// all sequences of internal whitespace are reduced to
        /// a single SP (ASCII 0x20) character.
        /// </summary>
        /// <param name="s">The string whose whitespace is to be normalized</param>
        /// <returns>a normalized string</returns>
        public static string NormalizeWS( this string @this )
        {
            string src        = @this ?? "" ;
            string normalized = rxWS.Replace( src , m =>{
                  bool isLeadingTrailingWS = ( m.Index == 0 || m.Index+m.Length == src.Length ? true : false ) ;
                  string p                 = ( isLeadingTrailingWS ? "" : " " ) ;
                  return p ;
                }) ;

            return normalized ;

        }
        private static Regex rxWS = new Regex( @"\s+" ) ;
    }
}
1

И еще одно:

public enum ParseFailBehavior
{
   ReturnNull,
   ReturnDefault,
   ThrowException
}

public static T? ParseNullableEnum<T>(this string theValue, ParseFailBehavior desiredBehavior = ParseFailBehavior.ReturnNull) where T:struct
{
   T output;
   T? result = Enum.TryParse<T>(theValue, out output) 
      ? (T?)output
      : desiredBehavior == ParseFailBehavior.ReturnDefault
         ? (T?)default(T)
         : null;

   if(result == null && desiredBehavior == ParseFailBehavior.ThrowException)
      throw new ArgumentException("Parse Failed for value {0} of enum type {1}".
         FormatWith(theValue, typeof(T).Name));       
}

Для этой версии требуется .NET 4.0; в 3.5 у вас нет TryParse и необязательных параметров; вы застряли с Enum.Parse(), который вы должны попробовать. Это все еще полностью выполнимо в 3.5 (и намного более полезно, поскольку Enum.Parse() является oogly и вашим единственным другим вариантом):

public static T? ParseNummableEnum<T>(this string theValue)
{
    return theValue.ParseNullableEnum<T>(ParseFailBehavior.ReturnNull);
}

public static T? ParseNullableEnum<T>(this string theValue, 
    ParseFailBehavior desiredBehavior) where T:struct
{
    try
    {
        return (T?) Enum.Parse(typeof (T), theValue);
    }
    catch (Exception)
    {
        if(desiredBehavior == ParseFailBehavior.ThrowException) throw;
    }

    return desiredBehavior == ParseFailBehavior.ReturnDefault ? (T?)default(T) : null;
}

Использование:

//returns null if OptionOne isn't an enum constant
var myEnum = "OptionOne".ParseNullableEnum<OptionEnum>(); 

//guarantees a return value IF the enum has a "zero" constant value (generally a good practice)
var myEnum = "OptionTwo".ParseNullableEnum<OptionEnum>(ParseFailBehavior.ReturnDefault).Value 
1

Перезаписать часть строки по указанному индексу.

Мне нужно работать с системой, которая ожидает, что некоторые входные значения будут фиксированными, фиксированными строками позиции.

public static string Overwrite(this string s, int startIndex, string newStringValue)
{
  return s.Remove(startIndex, newStringValue.Length).Insert(startIndex, newStringValue);
}

Итак, я могу сделать:

string s = new String(' ',60);
s = s.Overwrite(7,"NewValue");
  • 0
    Это хороший метод расширения, учитывая, что String.Replace не изменяет исходную строку.
1

ASP.NET Кодирование HTML - короткое и сладкое:

public static string ToHtmlEncodedString(this string s)
{
    if (String.IsNullOrEmpty(s))
        return s;
    return HttpUtility.HtmlEncode(s);
}
1

Несколько полезных расширений, если вы работаете с финансовыми годами

/// <summary>
/// Returns the fiscal year for the passed in date
/// </summary>
/// <param name="value">the date</param>
/// <returns>the fiscal year</returns>
public static int FiscalYear(this DateTime value)
{
  int ret = value.Year;
  if (value.Month >= 7) ret++;
  return ret;
}

/// <summary>
/// Returns the fiscal year for the passed in date
/// </summary>
/// <param name="value">the date</param>
/// <returns>the fiscal year</returns>
public static string FiscalYearString(this DateTime value)
{
  int fy = FiscalYear(value);
  return "{0}/{1}".Format(fy - 1, fy);
}
1

Я использую это все время:

public static void DelimitedAppend(this StringBuilder sb, string value, string delimiter)
{
    if (sb.Length > 0)
        sb.Append(delimiter);
    sb.Append(value);
}

Это просто гарантирует, что разделитель не вставлен, когда строка пуста. Например, чтобы создать разделенный запятыми список слов:

var farmAnimals = new[] { new { Species = "Dog", IsTasty = false }, new { Species = "Cat", IsTasty = false }, new { Species = "Chicken", IsTasty = true }, };
var soupIngredients = new StringBuilder();
foreach (var edible in farmAnimals.Where(farmAnimal => farmAnimal.IsTasty))
    soupIngredients.DelimitedAppend(edible.Species, ", ");
  • 9
    Намного более быстрый способ получить строку с разделителями - string.Join(",", strings); где strings это массив. Это генерирует примерно 1/3 IL как метод StringBuilder.
  • 0
    Ах, вау, хорошо, вы идете
Показать ещё 3 комментария
1

Ненавидеть этот вид кода?

CloneableClass cc1 = new CloneableClass ();
CloneableClass cc2 = null;
CloneableClass cc3 = null;

cc3 = (CloneableClass) cc1.Clone (); // this is ok
cc3 = cc2.Clone (); // this throws null ref exception
// code to handle both cases
cc3 = cc1 != null ? (CloneableClass) cc1.Clone () : null;

Это немного неуклюже, поэтому я заменяю его этим расширением, которое я называю CloneOrNull -

public static T CloneOrNull<T> (this T self) where T : class, ICloneable
{
    if (self == null) return null;
    return (T) self.Clone ();
}

Использование:

CloneableClass cc1 = new CloneableClass ();
CloneableClass cc2 = null;
CloneableClass cc3 = null;

cc3 = cc1.CloneOrNull (); // clone of cc1
cc3 = cc2.CloneOrNull (); // null
// look mom, no casts!

Пожалуйста, не стесняйтесь использовать это в любом месте!

1

Для ASP.NET я использую эти расширения для HttpSessionState для загрузки объектов в сеанс. Он позволяет загружать объекты сеанса чистым способом и будет создавать и инициализировать их, если они не существуют. Я использую два метода расширения следующим образом:

private bool CreateMode;
private MyClass SomeClass;

protected override void OnInit (EventArgs e)
{
    CreateMode = Session.GetSessionValue<bool> ("someKey1", () => true);
    SomeClass = Session.GetSessionClass<MyClass> ("someKey2", () => new MyClass () 
    { 
       MyProperty = 123 
    });
}

Вот классы расширения:

public static class SessionExtensions    
{
    public delegate object UponCreate ();
    public static T GetSessionClass<T> (this HttpSessionState session, 
       string key, UponCreate uponCreate) where T : class
    {
        if (null == session[key])
        {
            var item = uponCreate () as T;
            session[key] = item;
            return item;
        }
        return session[key] as T;
    }
    public static T GetSessionValue<T> (this HttpSessionState session, 
       string key, UponCreate uponCreate) where T : struct
    {
        if (null == session[key])
        {
            var item = uponCreate();
            session[key] = item;
            return (T)item;
        }
        return (T)session[key];
    }
}

код >

  • 0
    Используйте, как вы хотите для CodePlex или подкладка вашей клетке для птиц.
1

Некоторые удобные помощники строк:

Применение:

Я ненавижу ненужные пробелы или ведущие строки, и поскольку строка может принимать значение null, это может быть сложно, поэтому я использую это:

public bool IsGroup { get { return !this.GroupName.IsNullOrTrimEmpty(); } }

Вот еще один способ расширения, который я использую для новой рамки проверки, которую я тестирую. Вы можете видеть расширения регулярных выражений внутри этой помощи, чтобы очистить в противном случае грязное регулярное выражение:

public static bool IsRequiredWithLengthLessThanOrEqualNoSpecial(this String str, int length)
{
    return !str.IsNullOrTrimEmpty() &&
        str.RegexMatch(
            @"^[- \r\n\\\.!:*,@$%&""?\(\)\w']{1,{0}}$".RegexReplace(@"\{0\}", length.ToString()),
            RegexOptions.Multiline) == str;
}

Источник:

public static class StringHelpers
{
    /// <summary>
    /// Same as String.IsNullOrEmpty except that
    /// it captures the Empty state for whitespace
    /// strings by Trimming first.
    /// </summary>
    public static bool IsNullOrTrimEmpty(this String helper)
    {
        if (helper == null)
            return true;
        else
            return String.Empty == helper.Trim();
    }

    public static int TrimLength(this String helper)
    {
        return helper.Trim().Length;
    }

    /// <summary>
    /// Returns the matched string from the regex pattern. The
    /// groupName is for named group match values in the form (?<name>group).
    /// </summary>
    public static string RegexMatch(this String helper, string pattern, RegexOptions options, string groupName)
    {
        if (groupName.IsNullOrTrimEmpty())
            return Regex.Match(helper, pattern, options).Value;
        else
            return Regex.Match(helper, pattern, options).Groups[groupName].Value;
    }

    public static string RegexMatch(this String helper, string pattern)
    {
        return RegexMatch(helper, pattern, RegexOptions.None, null);
    }

    public static string RegexMatch(this String helper, string pattern, RegexOptions options)
    {
        return RegexMatch(helper, pattern, options, null);
    }

    public static string RegexMatch(this String helper, string pattern, string groupName)
    {
        return RegexMatch(helper, pattern, RegexOptions.None, groupName);
    }

    /// <summary>
    /// Returns true if there is a match from the regex pattern
    /// </summary>
    public static bool IsRegexMatch(this String helper, string pattern, RegexOptions options)
    {
        return helper.RegexMatch(pattern, options).Length > 0;
    }

    public static bool IsRegexMatch(this String helper, string pattern)
    {
        return helper.IsRegexMatch(pattern, RegexOptions.None);
    }

    /// <summary>
    /// Returns a string where matching patterns are replaced by the replacement string.
    /// </summary>
    /// <param name="pattern">The regex pattern for matching the items to be replaced</param>
    /// <param name="replacement">The string to replace matching items</param>
    /// <returns></returns>
    public static string RegexReplace(this String helper, string pattern, string replacement, RegexOptions options)
    {
        return Regex.Replace(helper, pattern, replacement, options);
    }

    public static string RegexReplace(this String helper, string pattern, string replacement)
    {
        return Regex.Replace(helper, pattern, replacement, RegexOptions.None);
    }
}

Мне нравится делать много регулярных выражений, поэтому я считаю их проще, чем добавление оператора using и дополнительного кода для обработки названных групп.

  • 0
    Ваш помощник IsNullOrTrimEmpty находится в .NET 4.0 в виде строки .IsEmptyOrWhiteSpace
  • 0
    @ICR: Привет, 5 CLR, ребята!
Показать ещё 1 комментарий
1

В ASP.NET мне всегда надоели с помощью FindControl, а затем пришлось бросать и проверять, имеет ли значение значение null перед ссылкой. Итак, я добавил метод TryParse() в Control, который отражает аналогичные в структуре для Int32 и т.д.

public static bool TryParse<T>(this Control control, string id, out T result) 
    where T : Control
{
    result = control.FindControl(id) as T;
    return result != null;
}

Теперь вы можете сделать это на страницах веб-формы ASP.NET:

Label lbl;
if (Page.TryParse("Label1", out lbl))
{
    lbl.Text = "Safely set text";
}
1

Шаблон для синтаксического анализа, который позволяет избежать out параметров:

public static bool TryParseInt32(this string input, Action<int> action)
{
    int result;
    if (Int32.TryParse(input, out result))
    {
        action(result);
        return true;
    }
    return false;
}

Использование:

if (!textBox.Text.TryParseInt32(number => label.Text = SomeMathFunction(number)))
    label.Text = "Please enter a valid integer";

Это можно поместить в проект codeplex, если это необходимо

1

Я всегда использую формат, который хочет новую строку с StringBuilder, поэтому самое простое расширение ниже сохраняет несколько строк кода:

public static class Extensions
{
    public static void AppendLine(this StringBuilder builder,string format, params object[] args)
    {
        builder.AppendLine(string.Format(format, args));
    }
}

Альтернативой является AppendFormat в StringBuilder с \n или Environment.NewLine.

  • 0
    Почему они не включили тот в BCL ...
  • 1
    не будет «build.AppendFormat (формат, аргументы); builder.AppendLine (); ´ будет больше в духе строителя строк (т.е. без временной строки)
Показать ещё 2 комментария
1

Несколько раз я обнаружил, что хочу что-то вроде, я думаю, Groovy "Безопасная навигация".

От http://groovy.codehaus.org/Statements:

Если вы идете по сложному объекту графика и не хотят иметь Выбросы NullPointerExceptions можно использовать?. оператора, а не. в выполните навигацию.

def foo = null def bar = foo?.something..myMethod() assert bar == null

Итак, как вы думаете, хорошая идея добавить для него метод расширения? Что-то вроде:

obj.SafelyNavigate(x => x.SomeProperty.MaybeAMethod().AnotherProperty);

Я думаю, было бы неплохо, даже если это может также вызвать некоторые проблемы.

Если вы думаете, что это хорошая идея:

  • Что вы думаете, что это должно произойти для типов значений?, вернуть значение по умолчанию? throw?, отключить его с помощью общего ограничения?.
  • Проглатывание NullReferenceException для его реализации было бы слишком рискованным?, Что ты предлагаешь?, Прогулка по дереву выражений, выполняющему каждый доступ к вызову или члену, кажется сложной и вроде излишней (если вообще возможно), не так ли?.

Может быть, это просто плохая идея: D, но я вижу это как что-то полезное, если все сделано правильно. Если нет ничего подобного, и вы думаете, что это имеет какое-то значение, я могу дать ему шанс и отредактировать ответ впоследствии.

  • 0
    требует .NET 3.5, использует делегаты для оценки графа объектов в try catch stackoverflow.com/questions/298009/…
  • 0
    Я думаю, что это может быть хорошей идеей, но это трудно реализовать ... Вы можете легко проверить, является ли x нулевым, но если вы хотите выполнить проверку для каждого уровня "пути" (SomeProperty, MaybeAMethod), он получает действительно трудно. Я попытался сделать это, переписав дерево выражений, но в конце концов сдался ...
Показать ещё 4 комментария
1

Inline Conversions: Мне нравится этот небольшой шаблон. Завершено для Boolean, Double и DateTime. Предназначен для работы с С# и как операторов.

public static Int32? AsInt32(this string s)
{
    Int32 value;
    if (Int32.TryParse(s, out value))
        return value;

    return null;
}

public static bool IsInt32(this string s)
{
    return s.AsInt32().HasValue;
}

public static Int32 ToInt32(this string s)
{
    return Int32.Parse(s);
{
  • 0
    Мне нравится, за исключением того, что я бы не сказал «есть» или «как», потому что это подразумевает сравнение / преобразование типов Это действительно метод синтаксического анализа.
  • 0
    Вы можете использовать ParseIsInt32 (), ParseToInt32 и ParseAsInt32 ()
1

Метод WhereIf()

var query = dc.Reviewer 
    .Where(r => r.FacilityID == facilityID) 
    .WhereIf(CheckBoxActive.Checked, r => r.IsActive); 

public static IEnumerable<TSource> WhereIf<TSource>(
    this IEnumerable<TSource> source,
    bool condition, Func<TSource, bool> predicate) 
{ 
    if (condition) 
        return source.Where(predicate); 
    else 
        return source; 
}

public static IQueryable<TSource> WhereIf<TSource>(
    this IQueryable<TSource> source,
    bool condition, Expression<Func<TSource, bool>> predicate) 
{ 
    if (condition) 
        return source.Where(predicate); 
    else 
        return source; 
}

Я также добавил перегрузки для предиката индекса в методе расширения Where(). Для большего удовольствия добавьте аромат, который содержит дополнительный предикат "else".

  • 0
    Мне не очень нравится этот. Где уже выполняет if, в этом весь смысл предиката.
  • 0
    Частично идея заключается в том, что некоторые условия не будут выполняться в SQL с IQueryable, поэтому их необходимо разделять.
1

Общий пример:

class Program
{
    static void Main(string[] args)
    {
        var z = 0;
        var a = 0.AsDefaultFor(() => 1 / z);
        Console.WriteLine(a);
        Console.ReadLine();
    }
}

public static class TryExtensions
{
    public static T AsDefaultFor<T>(this T @this, Func<T> operation)
    {
        try
        {
            return operation();
        }
        catch
        {
            return @this;
        }
    }
}

Поместите его в проект CodePlex, если хотите.

1

Преобразование любой строки для ввода Int32

// Calls the underlying int.TryParse method to convert a string
// representation of a number to its 32-bit signed integer equivalent.
// Returns Zero if conversion fails. 
public static int ToInt32(this string s)
{
    int retInt;
    int.TryParse(s, out retInt);
    return retInt;
}

ИСПОЛЬЗОВАНИЕ ОБРАЗЦОВ:
string s = "999";
int i = s.ToInt32();

1

Эквивалент метода соединения Python:

/// <summary>
/// same as python 'join'
/// </summary>
/// <typeparam name="T">list type</typeparam>
/// <param name="separator">string separator </param>
/// <param name="list">list of objects to be ToString'd</param>
/// <returns>a concatenated list interleaved with separators</returns>
static public string Join<T>(this string separator, IEnumerable<T> list)
{
    var sb = new StringBuilder();
    bool first = true;

    foreach (T v in list)
    {
        if (!first)
            sb.Append(separator);
        first = false;

        if (v != null)
            sb.Append(v.ToString());
    }

    return sb.ToString();
}
  • 7
    Вы можете заменить весь код в этой функции одной строкой: return string.Join(separator, list.ToArray());
1

Это метод расширения для вспомогательного метода ссылки ASP.Net MVC, который позволяет ему использовать атрибуты авторизации контроллера, чтобы решить, следует ли включать, отключать или скрывать ссылку из текущего пользовательского представления. Я избавляю вас от необходимости заключать ваши ограниченные действия в предложениях "если", которые проверяют членство пользователя во всех представлениях. Благодаря Maarten Balliauw для идеи и битов кода, которые показали мне способ:)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.Web.Routing;
using System.Web.Mvc;
using System.Collections;
using System.Reflection;
namespace System.Web.Mvc.Html
{
    public static class HtmlHelperExtensions
    {

        /// <summary>
        /// Shows or hides an action link based on the user membership status
        /// and the controller authorize attributes
        /// </summary>
        /// <param name="linkText">The link text.</param>
        /// <param name="action">The controller action name.</param>
        /// <param name="controller">The controller name.</param>
        /// <returns></returns>
        public static string SecurityTrimmedActionLink(
            this HtmlHelper htmlHelper,
            string linkText,
            string action,
            string controller)
        {
            return SecurityTrimmedActionLink(htmlHelper, linkText, action, controller, false, null);
        }

        /// <summary>
        /// Enables, disables or hides an action link based on the user membership status
        /// and the controller authorize attributes
        /// </summary>
        /// <param name="linkText">The link text.</param>
        /// <param name="action">The action name.</param>
        /// <param name="controller">The controller name.</param>
        /// <param name="showDisabled">if set to <c>true</c> [show link as disabled - 
        /// using a span tag instead of an anchor tag ].</param>
        /// <param name="disabledAttributeText">Use this to add attributes to the disabled
        /// span tag.</param>
        /// <returns></returns>
        public static string SecurityTrimmedActionLink(
            this HtmlHelper htmlHelper, 
            string linkText, 
            string action, 
            string controller, 
            bool showDisabled, 
            string disabledAttributeText)
        {
            if (IsAccessibleToUser(action, controller, HttpContext.Current ))
            {
                return htmlHelper.ActionLink(linkText, action, controller);
            }
            else
            {
                return showDisabled ? 
                    String.Format(
                        "<span{1}>{0}</span>", 
                        linkText, 
                        disabledAttributeText==null?"":" "+disabledAttributeText
                        ) : "";
            }
        }

        private static IController GetControllerInstance(string controllerName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Type controllerType = GetControllerType(controllerName);
            return (IController)Activator.CreateInstance(controllerType);
        }

        private static ArrayList GetControllerAttributes(string controllerName, HttpContext context)
        {
            if (context.Cache[controllerName + "_ControllerAttributes"] == null)
            {
                var controller = GetControllerInstance(controllerName);

                context.Cache.Add(
                    controllerName + "_ControllerAttributes",
                    new ArrayList(controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true)),
                    null,
                    Caching.Cache.NoAbsoluteExpiration,
                    Caching.Cache.NoSlidingExpiration,
                    Caching.CacheItemPriority.Default,
                    null);

            }
            return (ArrayList)context.Cache[controllerName + "_ControllerAttributes"];

        }

        private static ArrayList GetMethodAttributes(string controllerName, string actionName, HttpContext context)
        {
            if (context.Cache[controllerName + "_" + actionName + "_ActionAttributes"] == null)
            {
                ArrayList actionAttrs = new ArrayList();
                var controller = GetControllerInstance(controllerName);
                MethodInfo[] methods = controller.GetType().GetMethods();

                foreach (MethodInfo method in methods)
                {
                    object[] attributes = method.GetCustomAttributes(typeof(ActionNameAttribute), true);

                    if ((attributes.Length == 0 && method.Name == actionName)
                        ||
                        (attributes.Length > 0 && ((ActionNameAttribute)attributes[0]).Name == actionName))
                    {
                        actionAttrs.AddRange(method.GetCustomAttributes(typeof(AuthorizeAttribute), true));
                    }
                }

                context.Cache.Add(
                    controllerName + "_" + actionName + "_ActionAttributes",
                    actionAttrs,
                    null,
                    Caching.Cache.NoAbsoluteExpiration,
                    Caching.Cache.NoSlidingExpiration,
                    Caching.CacheItemPriority.Default,
                    null);

            }

            return (ArrayList)context.Cache[controllerName + "_" + actionName+ "_ActionAttributes"]; 
        }

        public static bool IsAccessibleToUser(string actionToAuthorize, string controllerToAuthorize, HttpContext context)
        {
            IPrincipal principal = context.User;

            //cache the attribute list for both controller class and it methods

            ArrayList controllerAttributes = GetControllerAttributes(controllerToAuthorize, context);

            ArrayList actionAttributes = GetMethodAttributes(controllerToAuthorize, actionToAuthorize, context);                        

            if (controllerAttributes.Count == 0 && actionAttributes.Count == 0)
                return true;

            string roles = "";
            string users = "";
            if (controllerAttributes.Count > 0)
            {
                AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
                roles += attribute.Roles;
                users += attribute.Users;
            }
            if (actionAttributes.Count > 0)
            {
                AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
                roles += attribute.Roles;
                users += attribute.Users;
            }

            if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
                return true;

            string[] roleArray = roles.Split(',');
            string[] usersArray = users.Split(',');
            foreach (string role in roleArray)
            {
                if (role == "*" || principal.IsInRole(role))
                    return true;
            }
            foreach (string user in usersArray)
            {
                if (user == "*" && (principal.Identity.Name == user))
                    return true;
            }
            return false;
        }

        private static Type GetControllerType(string controllerName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            foreach (Type type in assembly.GetTypes())
            {
                if (
                    type.BaseType!=null 
                    && type.BaseType.Name == "Controller" 
                    && (type.Name.ToUpper() == (controllerName.ToUpper() + "Controller".ToUpper())))
                {
                    return type;
                }
            }
            return null;
        }

    }
}
1

Некоторые расширения для работы со списками:

/// <summary>
/// Wrap an object in a list
/// </summary>
public static IList<T> WrapInList<T>(this T item)
{
    List<T> result = new List<T>();
    result.Add(item);
    return result;
}

используйте, например:

myList = someObject.InList();

Чтобы сделать IEnumerable, который содержит элементы из одного или нескольких источников, чтобы IEnumerable работал больше как списки. Это может быть не очень полезно для высокопроизводительного кода, но полезно для проведения тестов:

public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, T newItem)
{
    foreach (T item in enumerable)
    {
        yield return item;
    }

    yield return newItem;
}

public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, params T[] newItems)
{
    foreach (T item in enumerable)
    {
        yield return item;
    }

    foreach (T newItem in newItems)
    {
        yield return newItem;
    }
}

используйте, например,

someEnumeration = someEnumeration.Append(newItem);

Возможны другие варианты - например,

someEnumeration = someEnumeration.Append(otherEnumeration);

Если вы клонируете элементы, вы также можете клонировать их списки:

public static IList<T> Clone<T>(this IEnumerable<T> source) where T: ICloneable
{
    List<T> result = new List<T>();

    foreach (T item in source)
    {
        result.Add((T)item.Clone());
    }

    return result;
}

Когда я работаю с ObservableCollection<T>, я обычно расширяю его с помощью метода AddRange. Другие ответы здесь дают реализацию этого.

Вы можете поместить этот код в проект Codeplex, если хотите.

  • 1
    Почему бы не вернуть значения с помощью yield return и вернуть «фактические ленивые» перечислители? В определенной степени позаботится о вашем высокопроизводительном кодовом комментарии.
  • 0
    Я переименовал бы их в Append() (и использовал бы блоки итераторов, как предложено peSHlr)
Показать ещё 1 комментарий
1

Вот еще одна реализация ThrowIfNull:

[ThreadStatic]
private static string lastMethodName = null;

[ThreadStatic]
private static int lastParamIndex = 0;

[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowIfNull<T>(this T parameter)
{
    var currentStackFrame = new StackFrame(1);
    var props = currentStackFrame.GetMethod().GetParameters();

    if (!String.IsNullOrEmpty(lastMethodName)) {
        if (currentStackFrame.GetMethod().Name != lastMethodName) {
            lastParamIndex = 0;
        } else if (lastParamIndex >= props.Length - 1) {
            lastParamIndex = 0;
        } else {
            lastParamIndex++;
        }
    } else {
        lastParamIndex = 0;
    }

    if (!typeof(T).IsValueType) {
        for (int i = lastParamIndex; i &lt; props.Length; i++) {
            if (props[i].ParameterType.IsValueType) {
                lastParamIndex++;
            } else {
                break;
            }
        }
    }

    if (parameter == null) {
        string paramName = props[lastParamIndex].Name;
        throw new ArgumentNullException(paramName);
    }

    lastMethodName = currentStackFrame.GetMethod().Name;
}

Это не так эффективно, как другие импикменты, но имеет более чистое использование:

public void Foo()
{
    Bar(1, 2, "Hello", "World"); //no exception
    Bar(1, 2, "Hello", null); //exception
    Bar(1, 2, null, "World"); //exception
}

public void Bar(int x, int y, string someString1, string someString2)
{
    //will also work with comments removed
    //x.ThrowIfNull();
    //y.ThrowIfNull();
    someString1.ThrowIfNull();
    someString2.ThrowIfNull();

    //Do something incredibly useful here!
}

Изменение параметров на int? также будет работать.

-Билль

  • 0
    Код не полный.
  • 0
    на самом деле это было завершено, но меньшее, чем в цикле for было интерпретировано как тег ... просто изменило его на <
1

Мне нравятся эти расширения NUnit Assert: http://svn.caffeine-it.com/openrasta/trunk/src/Rasta.Testing/AssertExtensions.cs

  • 1
    Он всплывает с паролем. Просто нажмите Отмена.
0

Еще один, на этот раз, чтобы сделать UriBuilder более дружелюбным при работе с параметрами запроса.

    /// <summary>
    /// Adds the specified query parameter to the URI builder.
    /// </summary>
    /// <param name="builder">The builder.</param>
    /// <param name="parameterName">Name of the parameter.</param>
    /// <param name="value">The URI escaped value.</param>
    /// <returns>The final full query string.</returns>
    public static string AddQueryParam(this UriBuilder builder, string parameterName, string value)
    {
        if (parameterName == null)
            throw new ArgumentNullException("parameterName");

        if (parameterName.Length == 0)
            throw new ArgumentException("The parameter name is empty.");

        if (value == null)
            throw new ArgumentNullException("value");

        if (value.Length == 0)
            throw new ArgumentException("The value is empty.");

        if (builder.Query.Length == 0)
        {
            builder.Query = String.Concat(parameterName, "=", value);
        }
        else if
            (builder.Query.Contains(String.Concat("&", parameterName, "="))
            || builder.Query.Contains(String.Concat("?", parameterName, "=")))
        {
            throw new InvalidOperationException(String.Format("The parameter {0} already exists.", parameterName));
        }
        else
        {
            builder.Query = String.Concat(builder.Query.Substring(1), "&", parameterName, "=", value);
        }

        return builder.Query;
    }
0

Как насчет...

public static bool IsWinXPOrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && ((OS.Version.Major > 5) || ((OS.Version.Major == 5) && (OS.Version.Minor >= 1)));
}

public static bool IsWinVistaOrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && (OS.Version.Major >= 6);
}

public static bool IsWin7OrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && ((OS.Version.Major > 6) || ((OS.Version.Major == 6) && (OS.Version.Minor >= 1)));
}

public static bool IsWin8OrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && ((OS.Version.Major > 6) || ((OS.Version.Major == 6) && (OS.Version.Minor >= 2)));
}

Использование:

if (Environment.OSVersion.IsWinXPOrHigher())
{
  // do stuff
}

if (Environment.OSVersion.IsWinVistaOrHigher())
{
  // do stuff
}

if (Environment.OSVersion.IsWin7OrHigher())
{
  // do stuff
}

if (Environment.OSVersion.IsWin8OrHigher())
{
  // do stuff
}
0

Я использую следующие расширения для расширения всех коллекций (возможно, кто-то найдет их полезными):

/// <summary>
/// Collection Helper
/// </summary>
/// <remarks>
/// Use IEnumerable by default, but when altering or getting item at index use IList.
/// </remarks>
public static class CollectionHelper
{

    #region Alter;

    /// <summary>
    /// Swap item to another place
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="IndexA">Index a</param>
    /// <param name="IndexB">Index b</param>
    /// <returns>New collection</returns>
    public static IList<T> Swap<T>(this IList<T> @this, Int32 IndexA, Int32 IndexB)
    {
        T Temp = @this[IndexA];
        @this[IndexA] = @this[IndexB];
        @this[IndexB] = Temp;
        return @this;
    }

    /// <summary>
    /// Swap item to the left
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="Index">Index</param>
    /// <returns>New collection</returns>
    public static IList<T> SwapLeft<T>(this IList<T> @this, Int32 Index)
    {
        return @this.Swap(Index, Index - 1);
    }

    /// <summary>
    /// Swap item to the right
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="Index">Index</param>
    /// <returns>New collection</returns>
    public static IList<T> SwapRight<T>(this IList<T> @this, Int32 Index)
    {
        return @this.Swap(Index, Index + 1);
    }

    #endregion Alter;

    #region Action;

    /// <summary>
    /// Execute action at specified index
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="Index">Index</param>
    /// <param name="ActionAt">Action to execute</param>
    /// <returns>New collection</returns>
    public static IList<T> ActionAt<T>(this IList<T> @this, Int32 Index, Action<T> ActionAt)
    {
        ActionAt(@this[Index]);
        return @this;
    }

    #endregion Action;

    #region Randomize;

    /// <summary>
    /// Take random items
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="Count">Number of items to take</param>
    /// <returns>New collection</returns>
    public static IEnumerable<T> TakeRandom<T>(this IEnumerable<T> @this, Int32 Count)
    {
        return @this.Shuffle().Take(Count);
    }

    /// <summary>
    /// Take random item
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <returns>Item</returns>
    public static T TakeRandom<T>(this IEnumerable<T> @this)
    {
        return @this.TakeRandom(1).Single();
    }

    /// <summary>
    /// Shuffle list
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <returns>New collection</returns>
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> @this)
    {
        return @this.OrderBy(Item => Guid.NewGuid());
    }

    #endregion Randomize;

    #region Navigate;

    /// <summary>
    /// Get next item in collection and give first item, when last item is selected;
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="Index">Index in collection</param>
    /// <returns>Next item</returns>
    public static T Next<T>(this IList<T> @this, ref Int32 Index)
    {
        Index = ++Index >= 0 && Index < @this.Count ? Index : 0;
        return @this[Index];
    }

    /// <summary>
    /// Get previous item in collection and give last item, when first item is selected;
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <param name="Index">Index in collection</param>
    /// <returns>Previous item</returns>
    public static T Previous<T>(this IList<T> @this, ref Int32 Index)
    {
        Index = --Index >= 0 && Index < @this.Count ? Index : @this.Count - 1;
        return @this[Index];
    }

    #endregion Navigate;

    #region Clone;

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T">Collection type</typeparam>
    /// <param name="this">Collection</param>
    /// <returns>Cloned collection</returns>
    public static IEnumerable<T> Clone<T>(this IEnumerable<T> @this) where T : ICloneable
    {
        return @this.Select(Item => (T)Item.Clone());
    }

    #endregion Clone;

    #region String;

    /// <summary>
    /// Joins multiple string with Separator
    /// </summary>
    /// <param name="this">Collection</param>
    /// <param name="Separator">Separator</param>
    /// <returns>Joined string</returns>
    public static String Join(this IEnumerable<String> @this, String Separator = "")
    {
        return String.Join(Separator, @this);
    }

    #endregion String;

}
0

при сериализации и настройках лучше использовать long как DateTime, поэтому:

    public static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0);

    public static long ToUnixTimestamp(this DateTime dateTime)
    {
        return (long) (dateTime - Epoch).TotalSeconds;
    }

    public static long ToUnixUltraTimestamp(this DateTime dateTime)
    {
        return (long) (dateTime - Epoch).TotalMilliseconds;
    }

и назад

    public static DateTime ToDateTime(this long unixDateTime)
    {
        return Epoch.AddSeconds(unixDateTime);
    }

    public static DateTime ToDateTimeUltra(this long unixUltraDateTime)
    {
        return Epoch.AddMilliseconds(unixUltraDateTime);
    }
0

Если у вас есть персидский язык и должен показывать номера пользователям на персидском языке:

static public string ToFaString         (this string value)
        {
            // 1728 , 1584
            string result = "";
            if (value != null)
            {
                char[] resChar = value.ToCharArray();
                for (int i = 0; i < resChar.Length; i++)
                {
                    if (resChar[i] >= '0' && resChar[i] <= '9')
                        result += (char)(resChar[i] + 1728);
                    else
                        result += resChar[i];
                }
            }
            return result;
        }
  • 0
    Он не должен быть специфичным для персидского языка, вы можете заставить его работать для любой культуры (пример здесь ). Кроме того, вы должны использовать StringBuilder вместо конкатенации строк для повышения производительности
0

Если вам нужно проверить свою строку для Is All char равно 0:

 static public bool   IsAllZero            (this string input)
        {
            if(string.IsNullOrEmpty(input))
                return true;
            foreach (char ch in input)
            {
                if(ch != '0')
                    return false;
            }
            return true;
        }
  • 2
    Это немного излишне иметь что-то настолько специфичное, доступное для каждого строкового объекта в вашем приложении. Особенно, когда вы можете просто использовать myString.Any (c => c! = '0')
  • 0
    танкс за ваш комментарий
Показать ещё 1 комментарий
0

У нас есть средство развертывания для развертывания между средами. Поскольку файлы могут быть помечены как измененные, но не совсем разные, я пришел к следующему:

/// <summary>
/// Compares the files to see if they are different. 
/// First checks file size
/// Then modified if the file is larger than the specified size
/// Then compares the bytes
/// </summary>
/// <param name="file1">The source file</param>
/// <param name="file2">The destination file</param>
/// <param name="mb">Skip the smart check if the file is larger than this many megabytes. Default is 10.</param>
/// <returns></returns>
public static bool IsDifferentThan(this FileInfo file1, FileInfo file2, int mb = 10)
{
  var ret = false;

  // different size is a different file
  if(file1.Length != file2.Length) return true;

  // if the file times are different and the file is bigger than 10mb flag it for updating
  if(file1.LastWriteTimeUtc > file2.LastWriteTimeUtc && file1.Length > ((mb*1024)*1024)) return true;

  var f1 = File.ReadAllBytes(file1.FullName);
  var f2 = File.ReadAllBytes(file2.FullName);

  // loop through backwards because if they are different
  // it is more likely that the last few bytes will be different
  // than the first few
  for(var i = file1.Length - 1; i > 0; i--)
  {
    if(f1[i] != f2[i])
    {
      ret = true;
      break;
    }
  }

  return ret;
}
0

Сервер Sql имеет ограничение в ~ 2000 параметров, что является болью, если у вас есть идентификаторы 10 тыс. и требуется связанная с ними запись. Я написал эти методы, которые принимают пакетные списки идентификаторов и вызывается вот так:

List<Order> orders = dataContext.Orders.FetchByIds(
  orderIdChunks,
  list => row => list.Contains(row.OrderId)
);

List<Customer> customers = dataContext.Orders.FetchByIds(
  orderIdChunks,
  list => row => list.Contains(row.OrderId),
  row => row.Customer
);

public static List<ResultType> FetchByIds<RecordType, ResultType>(
    this IQueryable<RecordType> querySource,
    List<List<int>> IdChunks,
    Func<List<int>, Expression<Func<RecordType, bool>>> filterExpressionGenerator,
    Expression<Func<RecordType, ResultType>> projectionExpression
    ) where RecordType : class
{
    List<ResultType> result = new List<ResultType>();
    foreach (List<int> chunk in IdChunks)
    {
        Expression<Func<RecordType, bool>> filterExpression =
            filterExpressionGenerator(chunk);

        IQueryable<ResultType> query = querySource
            .Where(filterExpression)
            .Select(projectionExpression);

        List<ResultType> rows = query.ToList();
        result.AddRange(rows);
    }

    return result;
}

public static List<RecordType> FetchByIds<RecordType>(
    this IQueryable<RecordType> querySource,
    List<List<int>> IdChunks,
    Func<List<int>, Expression<Func<RecordType, bool>>> filterExpressionGenerator
    ) where RecordType : class
{
    Expression<Func<RecordType, RecordType>> identity = r => r;

    return FetchByIds(
        querySource,
        IdChunks,
        filterExpressionGenerator,
        identity
        );
}
0

Сравните равенство двух объектов без (обязательно) переопределения Equals или реализации IEquatable < > .

Зачем вам это нужно? Когда вы действительно хотите знать, равны ли два объекта, но вы слишком ленивы, чтобы переопределить Equals(object) или реализовать IEquatable<T>. Или, что более реалистично, если у вас есть ужасно сложный класс и реализация Equals вручную будет крайне утомительной, подверженной ошибкам, а не потерей поддержки. Это также помогает, если вы не слишком заботитесь о производительности.

В настоящее время я использую IsEqualTo из-за второй причины - у меня есть класс со многими свойствами, типы которых являются другими определяемыми пользователем классами, каждый из которых имеет много других свойств, типы которых являются другими определяемыми пользователем классами, ad infinitum, Бросьте кучу коллекций во многих из этих классов, а реализация Equals(object) действительно станет кошмаром.

Использование:

if (myTerriblyComplexObject.IsEqualTo(myOtherTerriblyComplexObject))
{
    // Do something terribly interesting.
}

Чтобы определить равенство, я делаю многочисленные сравнения. Я делаю все попытки сделать "правильный" в "правильном" порядке. Сопоставлениями являются:

  • Используйте статический метод Equals(object, object). Если он возвращает true, верните true. Он вернет true, если ссылки совпадают. Он также вернет true, если thisObject переопределяет Equals(object).
  • Если thisObject имеет значение null, верните значение false. Никаких дальнейших сравнений не может быть сделано, если оно равно нулю.
  • Если thisObject переопределило Equals(object), верните false. Поскольку он переопределяет Equals, это должно означать, что Equals был выполнен на шаге # 1 и возвращен false. Если кто-то потрудился переопределить Equals, мы должны это уважать и вернуть то, что возвращает Equals.
  • Если thisObject наследуется от IEquatable<T>, где otherObject может быть присвоено T, получите метод Equals(T), используя отражение. Вызовите этот метод и верните его возвращаемое значение.
  • Если оба объекта IEnumerable, верните ли они одни и те же элементы в том же порядке, используя IsEqualTo для сравнения элементов.
  • Если объекты имеют разные типы, верните false. Поскольку мы знаем теперь, что thisObject не имеет метода Equals, нет никакого способа реалистично оценить два объекта разных типов, чтобы они были истинными.
  • Если объекты представляют собой тип значения (примитив или структура) или строку, верните false. Мы уже провалили тест Equals(object) - достаточно сказали.
  • Для каждого свойства thisObject проверьте его значение с помощью IsEqualTo. Если какое-либо значение возвращает false, верните значение false. Если все возвращают true, верните true.

Сравнение строк может быть лучше, но легко реализовать. Кроме того, я не на 100% уверен, что правильно обрабатываю структуры.

Без дальнейшего исключения, вот способ расширения:

/// <summary>
/// Provides extension methods to determine if objects are equal.
/// </summary>
public static class EqualsEx
{
    /// <summary>
    /// The <see cref="Type"/> of <see cref="string"/>.
    /// </summary>
    private static readonly Type StringType = typeof(string);

    /// <summary>
    /// The <see cref="Type"/> of <see cref="object"/>.
    /// </summary>
    private static readonly Type ObjectType = typeof(object);

    /// <summary>
    /// The <see cref="Type"/> of <see cref="IEquatable{T}"/>.
    /// </summary>
    private static readonly Type EquatableType = typeof(IEquatable<>);

    /// <summary>
    /// Determines whether <paramref name="thisObject"/> is equal to <paramref name="otherObject"/>.
    /// </summary>
    /// <param name="thisObject">
    /// This object.
    /// </param>
    /// <param name="otherObject">
    /// The other object.
    /// </param>
    /// <returns>
    /// True, if they are equal, otherwise false.
    /// </returns>
    public static bool IsEqualTo(this object thisObject, object otherObject)
    {
        if (Equals(thisObject, otherObject))
        {
            // Always check Equals first. If the object has overridden Equals, use it. This will also capture the case where both are the same reference.
            return true;
        }

        if (thisObject == null)
        {
            // Because Equals(object, object) returns true if both are null, if either is null, return false.
            return false;
        }

        var thisObjectType = thisObject.GetType();
        var equalsMethod = thisObjectType.GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance, null, new[] { ObjectType }, null);
        if (equalsMethod.DeclaringType == thisObjectType)
        {
            // thisObject overrides Equals, and we have already failed the Equals test, so return false.
            return false;
        }

        var otherObjectType = otherObject == null ? null : otherObject.GetType();

        // If thisObject inherits from IEquatable<>, and otherObject can be passed into its Equals method, use it.
        var equatableTypes = thisObjectType.GetInterfaces().Where(                                          // Get interfaces of thisObjectType that...
            i => i.IsGenericType                                                                            // ...are generic...
            && i.GetGenericTypeDefinition() == EquatableType                                                // ...and are IEquatable of some type...
            && (otherObjectType ==  null || i.GetGenericArguments()[0].IsAssignableFrom(otherObjectType))); // ...and otherObjectType can be assigned to the IEquatable type.

        if (equatableTypes.Any())
        {
            // If we found any interfaces that meed our criteria, invoke the Equals method for each interface.
            // If any return true, return true. If all return false, return false.
            return equatableTypes
                .Select(equatableType => equatableType.GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance))
                .Any(equatableEqualsMethod => (bool)equatableEqualsMethod.Invoke(thisObject, new[] { otherObject }));
        }

        if (thisObjectType != StringType && thisObject is IEnumerable && otherObject is IEnumerable)
        {
            // If both are IEnumerable, check their items.
            var thisEnumerable = ((IEnumerable)thisObject).Cast<object>();
            var otherEnumerable = ((IEnumerable)otherObject).Cast<object>();

            return thisEnumerable.SequenceEqual(otherEnumerable, IsEqualToComparer.Instance);
        }

        if (thisObjectType != otherObjectType)
        {
            // If they have different types, they cannot be equal.
            return false;
        }

        if (thisObjectType.IsValueType || thisObjectType == StringType)
        {
            // If it is a value type, we have already determined that they are not equal, so return false.
            return false;
        }

        // Recurse into each public property: if any are not equal, return false. If all are true, return true.
        return !(from propertyInfo in thisObjectType.GetProperties()
                 let thisPropertyValue = propertyInfo.GetValue(thisObject, null)
                 let otherPropertyValue = propertyInfo.GetValue(otherObject, null)
                 where !thisPropertyValue.IsEqualTo(otherPropertyValue)
                 select thisPropertyValue).Any();
    }

    /// <summary>
    /// A <see cref="IEqualityComparer{T}"/> to be used when comparing sequences of collections.
    /// </summary>
    private class IsEqualToComparer : IEqualityComparer<object>
    {
        /// <summary>
        /// The singleton instance of <see cref="IsEqualToComparer"/>.
        /// </summary>
        public static readonly IsEqualToComparer Instance;

        /// <summary>
        /// Initializes static members of the <see cref="EqualsEx.IsEqualToComparer"/> class.
        /// </summary>
        static IsEqualToComparer()
        {
            Instance = new IsEqualToComparer();
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="EqualsEx.IsEqualToComparer"/> class from being created.
        /// </summary>
        private IsEqualToComparer()
        {
        }

        /// <summary>
        /// Determines whether the specified objects are equal.
        /// </summary>
        /// <param name="x">
        /// The first object to compare.
        /// </param>
        /// <param name="y">
        /// The second object to compare.
        /// </param>
        /// <returns>
        /// true if the specified objects are equal; otherwise, false.
        /// </returns>
        bool IEqualityComparer<object>.Equals(object x, object y)
        {
            return x.IsEqualTo(y);
        }

        /// <summary>
        /// Not implemented - throws an <see cref="NotImplementedException"/>.
        /// </summary>
        /// <param name="obj">
        /// The <see cref="object"/> for which a hash code is to be returned.
        /// </param>
        /// <returns>
        /// A hash code for the specified object.
        /// </returns>
        int IEqualityComparer<object>.GetHashCode(object obj)
        {
            throw new NotImplementedException();
        }
    }
}
0

И здесь расширение control-invoke я использую регулярно;

public static class InvokeExtensions
{
    public static void InvokeHandler(this Control control, MethodInvoker del) // Sync. control-invoke extension.
    {
        if (control.InvokeRequired)
        {
            control.Invoke(del);
            return; 
        }
        del(); // run the actual code.
    }

    public static void AsyncInvokeHandler(this Control control, MethodInvoker del) // Async. control-invoke extension.
    {
        if (control.InvokeRequired)
        {
            control.BeginInvoke(del);
            return; 
        }
        del(); // run the actual code.
    }
}

Пример

this.TreeView.AsyncInvokeHandler(() =>
        {
            this.Text = 'xyz'
        });

который позволяет кросс-нить gui-updates.

  • 0
    Я уверен, что этот уже был опубликован ранее ...
  • 0
    Может быть, я не проверил все ответы.
0

Ive создал метод расширения для выбора элемента в раскрывающемся списке ASP.NET.

Ниже приведен код

 public static class Utilities
{
    public enum DropDownListSelectionType
    {
        ByValue,
        ByText
    }

    public static void SelectItem(this  System.Web.UI.WebControls.DropDownList drp, string selectedValue, DropDownListSelectionType type)
    {
        drp.ClearSelection();
        System.Web.UI.WebControls.ListItem li;
        if (type == DropDownListSelectionType.ByValue)
            li = drp.Items.FindByValue(selectedValue.Trim());
        else
            li = drp.Items.FindByText(selectedValue.Trim());
        if (li != null)
            li.Selected = true;
    }}

Этот метод может быть вызван следующими строками кода для выбора по тексту

DropDownList1.SelectItem("ABCD", Utilities.DropDownListSelectionType.ByText);

или выберите значение

DropDownList1.SelectItem("11", Utilities.DropDownListSelectionType.ByValue);

Вышеприведенный код ничего не выбирает, если он не может найти переданный текст/значение.

0

Стиль Smalltalk, если /else в С#.

Не стесняйтесь ставить это на codeplex под любую лицензию, которую вы используете

using System;
namespace SmalltalkBooleanExtensionMethods
{

    public static class BooleanExtension
    {
        public static T ifTrue<T> (this bool aBoolean, Func<T> method)
        {
        if (aBoolean)
            return (T)method();
        else
            return default(T);
    }

        public static void ifTrue (this bool aBoolean, Action method)
        {
            if (aBoolean)
                method();
        }


        public static T ifFalse<T> (this bool aBoolean, Func<T> method)
        {
            if (!aBoolean)
                return (T)method();
            else
                return default(T);
        }

        public static void ifFalse (this bool aBoolean, Action method)
        {
            if (!aBoolean)
                method();
        }


        public static T ifTrueifFalse<T> (this Boolean aBoolean, Func<T> methodA, Func<T> methodB)
        {
            if (aBoolean)
                return (T)methodA();
            else
                return (T)methodB();
        }

        public static void ifTrueifFalse (this Boolean aBoolean, Action methodA, Action methodB)
        {
            if (aBoolean)
                methodA();
            else
                methodB();
        }

    }


}

Вероятно, у вас уже есть метод timesRepeat, но его там нет.

using System;

namespace SmalltalkBooleanExtensionMethods
{
    public static class IntExtension
    {
        public static int timesRepeat<T>(this int x, Func<T> method)
        {
            for (int i = x; i > 0; i--)
            {
                method();
            }

            return x;
        }

        public static int timesRepeat(this int x, Action method)
        {
            for (int i = x; i > 0; i--)
            {
                method();
            }

            return x;
        }
    }
}

Тесты Nunit

using System;
using SmalltalkBooleanExtensionMethods;
using NUnit.Framework;

namespace SmalltalkBooleanExtensionMethodsTest
{
    [TestFixture]
    public class SBEMTest
    {
        int i;
        bool itWorks;

        [SetUp]
        public void Init()
        {

            i = 0;
            itWorks = false;
        }

        [Test()]
        public void TestifTrue()
        {

            itWorks = (true.ifTrue(() => true));
            Assert.IsTrue(itWorks);
        }
        [Test()]
        public void TestifFalse()
        {
            itWorks = (false.ifFalse(() => true));
            Assert.IsTrue(itWorks);
        }

        [Test()]
        public void TestifTrueifFalse()
        {
            itWorks = false.ifTrueifFalse(() => false, () => true);
            Assert.IsTrue(itWorks);
            itWorks = false;
            itWorks = true.ifTrueifFalse(() => true, () => false);
            Assert.IsTrue(itWorks);
        }

        [Test()]
        public void TestTimesRepeat()
        {
            (5).timesRepeat(() => i = i + 1);
            Assert.AreEqual(i, 5);
        }

        [Test()]
        public void TestVoidMethodIfTrue()
        {

            true.ifTrue(() => SetItWorksBooleanToTrue());
            Assert.IsTrue(itWorks);
        }

        [Test()]
        public void TestVoidMethodIfFalse()
        {

            false.ifFalse(() => SetItWorksBooleanToTrue());
            Assert.IsTrue(itWorks);
        }

        public void TestVoidMethodIfTrueIfFalse()
        {
            true.ifTrueifFalse(() => SetItWorksBooleanToTrue(), () => SetItWorksBooleanToFalse());
            false.ifTrueifFalse(() => SetItWorksBooleanToFalse(), () => SetItWorksBooleanToTrue());
            Assert.IsTrue(itWorks);

        }

        public void TestVoidMethodTimesRepeat()
        {
            (5).timesRepeat(() => AddOneToi());
            Assert.AreEqual(i, 5);
        }

        public void SetItWorksBooleanToTrue()
        {
            itWorks = true;
        }

        public void SetItWorksBooleanToFalse()
        {
            itWorks = false;
        }

        public void AddOneToi()
        {
            i = i + 1;
        }
    }
}
  • 3
    Почему вы используете method.DynamicInvoke() ? Прямой вызов подобен этому: method() намного быстрее. stackoverflow.com/questions/932699/...
  • 0
    Материал, который я видел, показывающий, как вызывать лямбду, использовал .DynamicInvoke (), я не был уверен, что есть лучший способ.
Показать ещё 3 комментария
0

Этот не полностью испечен, поскольку мы только что придумали это сегодня утром. Он будет генерировать полное определение класса для типа. Полезно для ситуаций, когда у вас большой класс и вы хотите создать подмножество или полное определение, но не имеете к нему доступа. Например, чтобы сохранить объект в базе данных и т.д.

public static class TypeExtensions
{
    public static string GenerateClassDefinition(this Type type)
    {
        var properties = type.GetFields();
        var sb = new StringBuilder();
        var classtext = @"private class $name
        {
         $props}";

        foreach (var p in GetTypeInfo(type))
        {
            sb.AppendFormat("  public {0} {1} ", p.Item2, p.Item1).AppendLine(" { get; set; }");
        }

        return classtext.Replace("$name", type.Name).Replace("$props", sb.ToString());
    }

    #region Private Methods
    private static List<Tuple<string, string>> GetTypeInfo(Type type)
    {
        var ret = new List<Tuple<string, string>>();
        var fields = type.GetFields();
        var props = type.GetProperties();

        foreach(var p in props) ret.Add(new Tuple<string, string>(p.Name, TranslateType(p.PropertyType)));    
        foreach(var f in fields) ret.Add(new Tuple<string, string>(f.Name, TranslateType(f.FieldType)));

        return ret;
    }


    private static string TranslateType(Type input)
    {
        string ret;

        if (Nullable.GetUnderlyingType(input) != null)
        {
            ret = string.Format("{0}?", TranslateType(Nullable.GetUnderlyingType(input)));
        }
        else
        {
            switch (input.Name)
            {
                case "Int32": ret = "int"; break;
                case "Int64": ret = "long"; break;
                case "IntPtr": ret = "long"; break;
                case "Boolean": ret = "bool"; break;
                case "String":
                case "Char":
                case "Decimal":
                    ret = input.Name.ToLower(); break;
                default: ret = input.Name; break;
            }
        }

        return ret;
    }
    #endregion
}

Пример использования:

Process.GetProcesses().First().GetType().GenerateClassDefinition();

Становится еще более удобным, если вы используете linqpad:

Process.GetProcesses().First().GetType().GenerateClassDefinition().Dump();
  • 1
    Слишком много вещей не так с этим кодом.
  • 0
    Спасибо, Джим. Продолжайте конструктивные комментарии, очень полезно.
Показать ещё 14 комментариев
0
// This file contains extension methods for generic List<> class to operate on sorted lists.
// Duplicate values are OK.
// O(ln(n)) is still much faster then the O(n) of LINQ searches/filters.
static partial class SortedList
{
    // Return the index of the first element with the key greater then provided.
    // If there no such element within the provided range, it returns iAfterLast.
    public static int sortedFirstGreaterIndex<tElt, tKey>( this IList<tElt> list, Func<tElt, tKey, int> comparer, tKey key, int iFirst, int iAfterLast )
    {
        if( iFirst < 0 || iAfterLast < 0 || iFirst > list.Count || iAfterLast > list.Count )
            throw new IndexOutOfRangeException();
        if( iFirst > iAfterLast )
            throw new ArgumentException();
        if( iFirst == iAfterLast )
            return iAfterLast;

        int low = iFirst, high = iAfterLast;
        // The code below is inspired by the following article:
        // http://en.wikipedia.org/wiki/Binary_search#Single_comparison_per_iteration
        while( low < high )
        {
            int mid = ( high + low ) / 2;
            // 'mid' might be 'iFirst' in case 'iFirst+1 == iAfterLast'.
            // 'mid' will never be 'iAfterLast'.
            if( comparer( list[ mid ], key ) <= 0 ) // "<=" since we gonna find the first "greater" element
                low = mid + 1;
            else
                high = mid;
        }
        return low;
    }

    // Return the index of the first element with the key greater then the provided key.
    // If there no such element, returns list.Count.
    public static int sortedFirstGreaterIndex<tElt, tKey>( this IList<tElt> list, Func<tElt, tKey, int> comparer, tKey key )
    {
        return list.sortedFirstGreaterIndex( comparer, key, 0, list.Count );
    }

    // Add an element to the sorted array.
    // This could be an expensive operation if frequently adding elements that sort firstly.
    // This is cheap operation when adding elements that sort near the tail of the list.
    public static int sortedAdd<tElt>( this List<tElt> list, Func<tElt, tElt, int> comparer, tElt elt )
    {
        if( list.Count == 0 || comparer( list[ list.Count - 1 ], elt ) <= 0 )
        {
            // either the list is empty, or the item is greater then all elements already in the collection.
            list.Add( elt );
            return list.Count - 1;
        }
        int ind = list.sortedFirstGreaterIndex( comparer, elt );
        list.Insert( ind, elt );
        return ind;
    }

    // Find first exactly equal element, return -1 if not found.
    public static int sortedFindFirstIndex<tElt, tKey>( this List<tElt> list, Func<tElt, tKey, int> comparer, tKey elt )
    {
        int low = 0, high = list.Count - 1;

        while( low < high )
        {
            int mid = ( high + low ) / 2;
            if( comparer( list[ mid ], elt ) < 0 )
                low = mid + 1;
            else
                high = mid; // this includes the case when we've found an element exactly matching the key
        }
        if( high >= 0 && 0 == comparer( list[ high ], elt ) )
            return high;
        return -1;
    }

    // Return the IEnumerable that returns array elements in the reverse order.
    public static IEnumerable<tElt> sortedReverse<tElt>( this List<tElt> list )
    {
        for( int i=list.Count - 1; i >= 0; i-- )
            yield return list[ i ];
    }
}
0
public static class DictionaryExtensions
{
    public static Nullable<TValue> GetValueOrNull<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
        where TValue : struct
    {
        TValue result;
        if (dictionary.TryGetValue(key, out result))
            return result;
        else
            return null;
    }
}

Бесплатно, просто укажите мое имя (Янко Рёбиш) в коде.

0
public static class StringHelper
{
    public static String F(this String str, params object[] args)
    {
        return String.Format(str, args);
    }
}

Использование:

"Say {0}".F("Hello");
  • 4
    Этот ответ был уже предоставлен, путь наверх :(
0

Некоторые расширения DataSet/DataRow, чтобы упростить работу с db

Просто используйте .Field( "fieldname" ) в DataRow, и он будет отображать его, если он может, необязательный параметр по умолчанию может быть включен.

Также .HasRows() в DataSet, поэтому вам не нужно проверять наличие таблицы и строк.

Пример:

using (DataSet ds = yourcall()) 
{
  if (ds.HasRows())
  {
     foreach (DataRow dr in ds.Tables[0].Rows)
     {
        int id = dr.Field<int>("ID");
        string name = dr.Field<string>("Name");
        string Action = dr.Field<string>("Action", "N/A");
     }
  }
}

код:

using System;
using System.Data;

public static class DataSetExtensions
{
    public static T Field<T>(this DataRow row, string columnName, T defaultValue)
    {
        try
        {
            return row.Field<T>(columnName);
        }
        catch
        {
            return defaultValue;
        }
    }

    public static T Field<T>(this DataRow row, string columnName)
    {
        if (row[columnName] == null)
            throw new NullReferenceException(columnName + " does not exist in DataRow");

        string value = row[columnName].ToString();

        if (typeof(T) == "".GetType())
        {
            return (T)Convert.ChangeType(value, typeof(T));
        }
        else if (typeof(T) == 0.GetType())
        {
            return (T)Convert.ChangeType(int.Parse(value), typeof(T));
        }
        else if (typeof(T) == false.GetType())
        {
            return (T)Convert.ChangeType(bool.Parse(value), typeof(T));
        }
        else if (typeof(T) == DateTime.Now.GetType())
        {
            return (T)Convert.ChangeType(DateTime.Parse(value), typeof(T));
        }
        else if (typeof(T) == new byte().GetType())
        {
            return (T)Convert.ChangeType(byte.Parse(value), typeof(T));
        }
        else if (typeof(T) == new float().GetType())
        {
            return (T)Convert.ChangeType(float.Parse(value), typeof(T));
        }
        else
        {
            throw new ArgumentException(string.Format("Cannot cast '{0}' to '{1}'.", value, typeof(T).ToString()));
        }
    }

    public static bool HasRows(this DataSet dataSet) 
    {
        return (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0);
    }
}
  • 3
    Очень похоже на System.Data.DataSetExtensions.dll, которая поставляется с .NET 3.5, но не так эффективно.
0

В последнем разделе поиска на моей странице статистики блога я удалил все дубликаты, но мне нужен способ удаления почти дублированных строк. Я бы получил тонны похожих, но не совсем похожих запросов Google.

В итоге я использовал анонимный тип вместо словаря, но хотел создать список этого анонимного типа. Вы не можете этого сделать, но вы можете создать List<dynamic> в .NET 4.0:)

В основном мне это нравится, потому что я действительно получаю List<AnonymousType#1>().

/// <summary>Remove extraneous entries for common word permutations</summary>
/// <param name="input">Incoming series of words to be filtered</param>
/// <param name="MaxIgnoreLength">Words this long or shorter will not count as duplicates</param>
/// <param name="words2">Instance list from BuildInstanceList()</param>
/// <returns>Filtered list of lines from input, based on filter info in words2</returns>
private static List<string> FilterNearDuplicates(List<string> input, int MaxIgnoreLength, List<dynamic> words2)
{
    List<string> output = new List<string>();
    foreach (string line in input)
    {
        int Dupes = 0;
        foreach (string word in line.Split(new char[] { ' ', ',', ';', '\\', '/', ':', '\"', '\r', '\n', '.' })
            .Where(p => p.Length > MaxIgnoreLength)
            .Distinct())
        {
            int Instances = 0;
            foreach (dynamic dyn in words2)
            if (word == dyn.Word)
            {
                Instances = dyn.Instances;
                if (Instances > 1)
                    Dupes++;
                break;
            }
        }
        if (Dupes == 0)
            output.Add(line);
    }
    return output;
}
/// <summary>Builds a list of words and how many times they occur in the overall list</summary>
/// <param name="input">Incoming series of words to be counted</param>
/// <returns></returns>
private static List<dynamic> BuildInstanceList(List<string> input)
{
    List<dynamic> words2 = new List<object>();
    foreach (string line in input)
    foreach (string word in line.Split(new char[] { ' ', ',', ';', '\\', '/', ':', '\"', '\r', '\n', '.' }))
    {
        if (string.IsNullOrEmpty(word))
            continue;
        else if (ExistsInList(word, words2))
            for (int i = words2.Count - 1; i >= 0; i--)
            {
                if (words2[i].Word == word)
                    words2[i] = new { Word = words2[i].Word, Instances = words2[i].Instances + 1 };
            }
        else
            words2.Add(new { Word = word, Instances = 1 });
    }

    return words2;
}
/// <summary>Determines whether a dynamic Word object exists in a List of this dynamic type.</summary>
/// <param name="word">Word to look for</param>
/// <param name="words">Word dynamics to search through</param>
/// <returns>Indicator of whether the word exists in the list of words</returns>
private static bool ExistsInList(string word, List<dynamic> words)
{
    foreach (dynamic dyn in words)
        if (dyn.Word == word)
            return true;
    return false;
}
0

А почему бы и нет! Здесь расширение для IList (не может быть IEnumerable, потому что я использую особенности списка) для сортировки вставки.

internal static class SortingHelpers
{
    /// <summary>
    /// Performs an insertion sort on this list.
    /// </summary>
    /// <typeparam name="T">The type of the list supplied.</typeparam>
    /// <param name="list">the list to sort.</param>
    /// <param name="comparison">the method for comparison of two elements.</param>
    /// <returns></returns>
    public static void InsertionSort<T>(this IList<T> list, Comparison<T> comparison)
    {
        for (int i = 2; i < list.Count; i++)
        {
            for (int j = i; j > 1 && comparison(list[j], list[j - 1]) < 0; j--)
            {
                T tempItem = list[j];
                list.RemoveAt(j);
                list.Insert(j - 1, tempItem);
            }
        }
    }
}

Пример:

List<int> list1 = { 3, 5, 1, 2, 9, 4, 6 };
list1.InsertionSort((a,b) => a - b);
//list is now in order of 1,2,3,4,5,6,9
  • 0
    Нет примера? Это довольно просто, но, возможно, не для всех
  • 0
    Там как это?
Показать ещё 5 комментариев
0
// Checks for an empty collection, and sends the value set in the default constructor for the desired field
public static TResult MinGuarded<T, TResult>(this IEnumerable<T> items, Func<T, TResult> expression) where T : new() {
    if(items.IsEmpty()) {
        return (new List<T> { new T() }).Min(expression);
    }
    return items.Min(expression);
}

// Checks for an empty collection, and sends the value set in the default constructor for the desired field
public static TResult MaxGuarded<T, TResult>(this IEnumerable<T> items, Func<T, TResult> expression) where T : new() {
    if(items.IsEmpty()) {
        return (new List<T> { new T() }).Max(expression);
    }
    return items.Max(expression);
}

Я не уверен, есть ли лучший способ сделать это, но это расширение очень полезно, когда я хочу иметь контроль над значениями по умолчанию для полей в моем объекте. Например, если я хочу контролировать значение DateTime и хочу быть установленным в соответствии с моей бизнес-логикой, тогда я могу сделать это в конструкторе по умолчанию. В противном случае это будет DateTime.MinDate.

0

Возможно, наиболее полезные методы расширения, которые я написал и использовал, следующие:

http://www.codeproject.com/KB/cs/fun-with-cs-extensions.aspx?msg=2838918#xx2838918xx

0
// Values ordered true/false
// True/false values separated by a capital letter
// Only two values allowed
// ---------------------------
// Limited, but could be useful
public enum BooleanFormat
{
    OneZero,
    YN,
    YesNo,
    TF,
    TrueFalse,
    PassFail,
    YepNope
}

public static class BooleanExtension
{
    /// <summary>
    /// Converts the boolean value of this instance to the specified string value. 
    /// </summary>
    private static string ToString(this bool value, string passValue, string failValue)
    {
        return value ? passValue : failValue;
    }

    /// <summary>
    /// Converts the boolean value of this instance to a string. 
    /// </summary>
    /// <param name="booleanFormat">A BooleanFormat value. 
    /// Example: BooleanFormat.PassFail would return "Pass" if true and "Fail" if false.</param>
    /// <returns>Boolean formatted string</returns>
    public static string ToString(this bool value, BooleanFormat booleanFormat)
    {
        string booleanFormatString = Enum.GetName(booleanFormat.GetType(), booleanFormat);
        return ParseBooleanString(value, booleanFormatString);      
    }

    // Parses boolean format strings, not optimized
    private static string ParseBooleanString(bool value, string booleanFormatString)
    {
        StringBuilder trueString = new StringBuilder();
        StringBuilder falseString = new StringBuilder();

        int charCount = booleanFormatString.Length;

        bool isTrueString = true;

        for (int i = 0; i != charCount; i++)
        {
            if (char.IsUpper(booleanFormatString[i]) && i != 0)
                isTrueString = false;

            if (isTrueString)
                trueString.Append(booleanFormatString[i]);
            else
                falseString.Append(booleanFormatString[i]);
        }

        return (value == true ? trueString.ToString() : falseString.ToString());
    }
0
  • Для добавления нескольких элементов в коллекцию, у которой нет AddRange, например collection.Add(item1, item2, itemN);

    static void Add<T>(this ICollection<T> coll, params T[] items)
     { foreach (var item in items) coll.Add(item);
     }
    
  • Ниже приведен пример string.Format(), но с пользовательским строковым представлением аргументов, например, "{0} {1} {2}".Format<Custom>(c=>c.Name,"string",new object(),new Custom()) приводит к "string {System.Object} Custom1Name"

    static string Format<T>(  this string format
                            , Func<T,object> select
                            , params object[] args)
     { for(int i=0; i < args.Length; ++i)
        { var x = args[i] as T;
          if (x != null) args[i] = select(x);
        }
       return string.Format(format, args);
     }
    
-4

Получает корневой домен URI.

/// <summary>Gets the root domain of any URI</summary>
/// <param name="uri">URI to get root domain of</param>
/// <returns>Root domain with TLD</returns>
public static string GetRootDomain(this System.Uri uri)
{
    if (uri == null)
        return null;

    string Domain = uri.Host;
    while (System.Text.RegularExpressions.Regex.Matches(Domain, @"[\.]").Count > 1)
        Domain = Domain.Substring(Domain.IndexOf('.') + 1);
    Domain = Domain.Substring(0, Domain.IndexOf('.'));
    return Domain;
}
  • 5
    Это кажется немного ошибочным в предположении структуры FQDN - попробуйте эти контрольные примеры. www.msn.co.uk против www.msn.com против msn.co.uk co определенно не является корневым доменом для msn.co.uk.
-12

Легко сериализуйте объекты в XML:

public static string ToXml<T>(this T obj) where T : class
{
    XmlSerializer s = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        s.Serialize(writer, obj);
        return writer.ToString();
    }
}

"<root><child>foo</child</root>".ToXml<MyCustomType>();
  • 2
    Использование неверно.
  • 0
    также дубликат stackoverflow.com/questions/271398/…
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню