C #에서 가장 좋아하는 확장 방법은 무엇입니까? (codeplex.com/extensionoverflow)


478

우수하고 선호하는 확장 방법 을 게시하는 답변 목록을 만들어 봅시다 .

요구 사항은 전체 코드를 게시하고 사용 방법에 대한 예와 설명을 게시해야합니다.

이 주제에 대한 높은 관심을 바탕으로 Codeplex에 extensionoverflow라는 오픈 소스 프로젝트를 설정했습니다 .

Codeplex 프로젝트에 코드를 넣을 수 있도록 답을 표시하십시오.

링크가 아닌 전체 소스 코드를 게시하십시오.

Codeplex 뉴스 :

24.08.2010 Codeplex 페이지는 다음과 같습니다 : http://extensionoverflow.codeplex.com/

2008년 11월 11일 XMLSERIALIZE / XmlDeserialize는 지금 구현 및 단위 테스트 .

11.11.2008 더 많은 개발자를위한 여지가 여전히 남아 있습니다. ;-) 지금 가입하십시오!

2008 년 11 월 11 일 세 번째 제공자가 ExtensionOverflow 에 합류 하여 BKristensen에 오신 것을 환영합니다

2008년 11월 11일 FormatWith는 지금 구현 및 단위 테스트 .

2008 년 9 월 11 일 두 번째 제공자가 ExtensionOverflow 에 합류했습니다 . chakrit에 오신 것을 환영합니다 .

2008 년 9 월 11 일 더 많은 개발자가 필요합니다. ;-)

2008 년 9 월 11 일 ThrowIfArgumentIsNull 은 이제 Codeplex 에서 구현 및 테스트 되었습니다.


이제 첫 번째 코드는 Codeplex 사이트에 적용됩니다.
— bovium

에릭 불행히도 모든 것이 이제 코드 플렉스에서 시작됩니다. 어쨌든 가입하십시오.
— bovium

3
꽤 좋아 보인다. 정적 클래스의 이름을 지정하는 것에 대한 의견이 있습니다. <type> 확장명을 지정하는 것은 그리 유익하지 않습니다. 예를 들어 StringExtensions는 서식과 XML을 모두 보유합니다. 그 유형을 확장하는 이유와 함께 클래스 이름을 지정하는 것이 좋습니다. 예를 들어 UnixDateTimeConversions입니다. 유닉스 시간과의 변환 방법을 가지고 있다고 합리적으로 추측 할 수 있습니다. 그냥 생각!
— ecoffey

C # 확장 방법에 대한 자세한 내용은이 URL을 확인하십시오 planetofcoders.com/c-extension-methods
— Gaurav Agrawal

답변:


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

2
System.Linq를 사용하고 있다면 컴파일이됩니다.
— Ryu

11
"EqualsAnyOf"가 "In"보다 나은 이름일까요?
— Tom Bushell

10
나는 그것을 좋아하는지 확신하지 못한다-나는의 간결함을 좋아 In하지만 어쩌면 IsIn더 좋을 것이다.
— Winston Smith

50
같은 Contains 메소드 사용 : (new [] {1, 2, 3}). 포함 (a)
— Max Toro

4
나는 또한 생각 In<T>(...)하고 표준 라이브러리 외부에서 가장 유용한 확장 방법이라는 것을 알았습니다. 그러나 나는 그 이름과 모순된다 In. 메소드 이름은 그 기능을 설명해야하지만 In그렇게하지는 않습니다. 나는 그것을 불렀지 IsAnyOf<T>(...)만 충분할 IsIn<T>(...)것 같아요 .
— JBSnorro

160

MiscUtil 프로젝트 에 다양한 확장 방법 이 있습니다 (전체 소스를 사용할 수 있습니다-여기서는 반복하지 않겠습니다). 내가 좋아하는 것 중 일부는 다른 수업 (예 : 범위)과 관련이 있습니다.

날짜 및 시간 항목-대부분 단위 테스트에 사용됩니다. 프로덕션에서 사용할 것인지 확실하지 않습니다. :)

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

범위와 스테핑-Marc Gravell에게 이를 가능하게하는 운영자의 작업 에 감사드립니다 .

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
멋지다! 나는 그것을 읽을 P는있을거야 약속 :-) 몇 가지 패치를 보낼 수 있도록 Google 코드 또는 코드 플렉스에 그것을 넣어해야
— chakrit

3
@bovium : 이미 코드를 볼 수 있습니다. 첫 번째 문장의 링크를 따르십시오-전체 소스가 있습니다.
— Jon Skeet

1
@bovium : 마음에 들지 않으면 code.google.com에 넣고 직접 프로젝트를 관리하고 싶습니다. 적절한 귀속을 유지하는 경우 분명히 Codeplex에 라이센스를 부여 할 수 있습니다. 그러나 필사적이지 않으면 조만간 정리하겠습니다. :)
— Jon Skeet

1
@ 존 스케 트. 모든 사람에게 무료로 MIT 라이센스가 적용됩니다. 상업적 또는 오픈 소스. 힘을 합쳐서 대중을위한 확장 메소드 라이브러리를 만드십시오.
— bovium

1
그 라이브러리에서 다른 많은 비트와 조각을 수행하기 때문에. 귀하의 프로젝트를 위해 모든 사본을 준비하는 것을 환영하지만, 내 프로젝트에도 사본을 보관하고 싶습니다.
— Jon Skeet

147

문자열. 형식 바로 가기 :

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
확실히 짧지 만 새로운 팀원은 읽을 수 없습니다.
— Jon Skeet

3
가독성은 빠르게 찾아보고 물어볼 수있는 몇 가지 간단한 설명보다 코드의 더 큰 체계에서 더 중요하다고 생각합니다.
— chakrit

6
개인적으로 BCL이 한 번의 패턴을 구문 분석하고 재사용 할 수있는 별도의 Formatter 객체를 원합니다. 가독성과 성능이 향상됩니다. 나는 BCL 팀을 요청했습니다 - 우리가 볼거야 ...
— 존 소총

3
그것은 확장 방법입니다. 물론 팀의 새로운 멤버는 읽을 수 없습니다. 나는 이것이 재치있는 물건이라고 생각했다? 신입 회원은 우리가 얼마나 영리한지 어떻게 알 수 있습니까?
— MarkJ

17
좋아 ... 방금 이것을 행동으로 옮기고 .With와 함께 갔다. "This is a {0}". With ( "test") 그리고 매우 읽기 쉽고 의미가 있습니다. 참고
— klkitchens

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

이것은 파이썬 random.choice (seq) 함수를 모방합니다. 좋은.
— Daren Thomas

6
몇 가지 : 나는 어떤 것을 OneOf받아들이는 것이 좋습니다 . 그런 다음 항상 arg를 사용하고 과부하 로 전달 하는 과부하를 가질 수 있습니다 . 나는 당신과 비슷한 방법 으로 매개 변수 를 취하는 과부하 (지금 75 %의 시간을 원한다면 어떻게해야합니까?) 로 대답을했습니다 (지금 아래쪽에서 아래로 내려 갑니다 ). 또한 nit pick : 예제 코드는 이후 초기화되지 않습니다. IList<T>paramsIList<T>NextBoolCoinTossprobabilityNullReferenceExceptionrand
— Dan Tao

3
+1 나는 이것을 정말로 좋아하지만 내부적 으로 만들어 지기 때문에 CoinToss구현하기를 선호 하므로 캐스트, * 및 수표를 저장하십시오. rng.NextDouble() < .5.Next(int).NextDouble()
— Lasse Espeholt

76
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))
{
  // ....
}

19
나는 이것을 좋아하지만 최소값은 포함하지만 최대 값은 독점적으로 경계 검사를 수행하는 것이 옳은지 결정하려고합니다. 혼란 스러운지 궁금합니다. 5.Between (5,10)은 true이지만 5.Between (1,5)는 false입니다. 메서드 내의 동반자가 도움이 될지조차 확실하지 않습니다. 응?
— Steve Hiner

12
"IsBetween"이라는 이름이 더 의미가 없습니까? 또한 IsBetweenInclusive 및 IsBetweenExclusive를 만들 수도 있습니다. 그래도 어느 것을 기본값으로 취해야할지 모르겠습니다.
— fretje 2016 년

2
@Steve : 날짜 시간 연장 인 경우 더 의미가 있습니다.
— Joel Coehoorn

16
5.Between (5,10)은 false를 반환하고 10.Between (5,10)도 false를 반환합니다. 그것은 자연스럽게 느껴집니다.
— Alex Baranosky

3
여러 사람들이 자연스러운 것에 대해 다른 생각을 가지고있는 것 같습니다. 이 때문에 매우 쉬운 오류의 원인이 될 수 있으므로 사용중인 항목 (즉, 포함 대 독점)을 명시 적으로 명시해야합니다.
— David Miani

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};
— 아르 니스 Lapsa

왜 메소드 내에서 List <T> .AddRange (IEnumerable <T> collection)를 호출하지 않습니까?
— Rauhotz

8
@Will : 사실, 그것은 것입니다 최고의 에 동의 ICollection<T>; 예를 들어 인덱스 컬렉션뿐만 아니라 LinkedList<T>및 에 사용될 수도 있습니다 HashSet<T>.
— Dan Tao

2
pre..net 4.0에서 공분산 을 허용하도록 편집
— BlueRaja-Danny Pflughoeft

55

반드시 이것을 코드 플렉스 프로젝트에 넣으십시오.

객체를 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.
    }
}

8
나는 첫 번째 전화를 유혹 할 것이다 ToXml()(같은 ToString())
— 제이 Bazuzi

1
그가 의도적으로 OP를 쓴다면 OP에 사과했지만 MemoryStreams AND XmlReader / XmlWriter를 사용하는 것은 과잉이었습니다. StringReader 및 StringWriter 클래스는이 작업에 적합합니다.
— 포트만

2
이것은 스레드 안전이 아닙니다. 정적 직렬 변환기 사전에 대한 액세스를 반드시 동기화해야합니다.
— Yann Schwartz

2
@Yann, @T, "스레드 정적"속성 만 추가하면 훨씬 쉽습니다. 그런 다음 스레드마다 새 캐시가 작성됩니다. 동기화가 필요 없습니다.
— Frank Krueger

1
@Jonathan C Dickinson : MSDN 문서 ( msdn.microsoft.com/en-us/library/…) 에서 사용 된 생성자 (새 XmlSerializer (type))에 메모리 누수 문제가없는 것으로 보입니다 . 캐싱 코드가 필요하지 않습니까?
— slolife

46

IEnumerables를위한 ForEach

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를 사용하면 변환 / 데이터 조작없이 각 항목에 대해 무언가를 실행할 수 있습니다.

나는 이것을 더 기능적인 스타일로 프로그래밍 할 수 있도록 만들었고 IEnumerable은 그렇지 않지만 List에는 ForEach가 있다는 것에 놀랐습니다.

이것을 코드 플렉스 프로젝트에 넣으십시오.


13
LINQ의 IEnumerable <T> 확장에 ForEach가 포함되지 않은 이유에 대한 게시물 : stackoverflow.com/questions/317874/…
— Neil

13
방법을 사용하기 전에 이것을 읽는 것이 좋습니다 : blogs.msdn.com/ericlippert/archive/2009/05/18/…
— jpbochi

2
@ jpbochi : 이것은 단지 Microsoft demagogy입니다
— abatishchev

1
@abatishchev 그리고 귀하의 의견은 Microsoft에 대한 편견입니다. Eric이 쓴 어떤 단어도 무효화하지 않습니다. 누군가의 주장은 자신이 일하는 회사 때문에 유효하거나 유효하지 않습니다.
— jpbochi

1
그건 그렇고, 한 가지 요점을 분명히 해 드리겠습니다. 이 ForEach 확장 방법을 사용해서는 안된다고 말하지 않았습니다. 방금 Eric의 사용 여부를 결정하기 전에 Eric이 노출 한 점을 고려해야한다고 말했습니다. 나는 그것을 읽고 사용하지 않기로 결정했습니다. 코드로 원하는 것을 자유롭게 할 수 있습니다.
— jpbochi

43

귀하가 할 수있는 전환 확장 프로그램 :

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"), "기본"값을 지정하거나 ( "기타"라고 함) null을 요청할 수 있습니다 (여기서 T : 클래스). 또한 자동 예외 모델과 수행 한 작업을 나타내는 bool을 반환하는 전형적인 TryParse 모델을 제공했으며 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 분 동안 노력했습니다.


64
개인적으로, 나는 결과를 결정하려고 노력하는 코드 팬이 아닙니다. 의도 된 로직 IMO 외부에서 발생하는 오류에 대해서는 Try / Catch를 사용해야합니다. hmmmmm
— Pure.Krome

코드를 사용하지 않으려면 게시하지 않았을 것입니다! :)
— TheSoftwareJedi

마침내 보이지 않는 것. 나는 그것을 좋아한다. :)
— Arnis Lapsa

8
최소한 "catch"절을 변경하여 참조를 "변환"할 수없는 경우 ChangeType ()에서 발생하는 예외 만 포착해야합니다. OutOfMemoryException, ExecutionEngineException, ThreadAbortException 등을 변환 오류로 처리하고 싶지 않다고 생각합니다. 그렇지 않으면 오류를 추적하기가 매우 어려울 것입니다.
— Christian.K

2
나는 ToOrNull똑같은 동작을 가지고 있다고 생각 합니다 ToOrDefault(즉, ToOrDefault변환에 실패한 참조 유형 을 호출 하면을 반환합니다 null). 그러나 더 중요한 var s = myObject as string것은 var s = myObject.ToOrNull<string>()잠재적으로을 잡을 필요없이 동일한 것을 달성 한 이후 나에게 중복되는 것처럼 보입니다 InvalidCastException. 뭔가 빠졌습니까?
— Dan Tao

43

예외 로깅을위한 확장 방법이 있습니다.

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

그리고 그것은 다음과 같이 사용됩니다 :

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

[두 번 게시해서 죄송합니다. 두 번째는 더 잘 설계되었습니다 :-)]


2
public static void Log (this obj obj) {}를 읽어야합니까?
— Chris S

이것이 BCL 또는 타사 예외에는 유용하다고 생각하지만 자체 예외 유형을 롤하면 기본 예외 클래스에 로깅을 배치 할 수 있습니다. 그렇게하면 Log ()를 호출 할 필요가 없습니다.
— si618

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

신용은 Scott Dorman 에게 간다

--- Codeplex 프로젝트 편집 ---

Scott Dorman에게 Codeplex 프로젝트에서 코드를 게시 할 수 있는지 물어 봤습니다. 이것은 내가 그에게서받은 대답입니다.

SO 포스트와 CodePlex 프로젝트에 대한 연구에 감사드립니다. 질문에 대한 귀하의 답변을지지했습니다. 그렇습니다. 코드는 현재 CodeProject Open License ( http://www.codeproject.com/info/cpol10.aspx ) 에 따라 퍼블릭 도메인에 있습니다 .

CodePlex 프로젝트에 포함되는 데 아무런 문제가 없으며 프로젝트에 나를 추가하려면 (사용자 이름은 sdorman입니다) 해당 메소드와 추가 열거 도우미 메소드를 추가합니다.


이 열거 구문 분석 시나리오는 항상 나타납니다 ... 내 라이브러리에 이것을 넣어야합니다 :-)
— chakrit

와우, 문자열을 열거 형에 매핑하는 메서드를 작성했습니다 (방금 .NET을 사용하여 시작했습니다). 고마워, 이것은 절대적으로 도움이 될 것입니다!
— 케빈

4
이 ToEnum <> ()의 이름은 객체 뒤에옵니다.
— Neil

- Enum.TryParse <T는> 인터넷 4.0에 추가 된 것을 참고 blogs.msdn.com/bclteam
— 댄 디플을

1
이 방법이 트림을 사용해야한다고 생각하지 않습니다. 입력을 다듬는 것은 호출자의 책임입니다.
— 코드 InChaos

32

나는 이것이 매우 유용하다는 것을 알았다.

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

CodePlex에서 사용할 수 있습니다.


2
누군가가 우리에게 덜 재능이 있다고 설명 할만큼 친절 할 수 있습니까?
— jpbochi

hahaha 그냥 기사 (위의 Joel의 의견)를 읽으십시오. 재미있는 사실이지만 Paula가 아닌 수신 쪽에서 거의 같은 보트에 있었기 때문에 다시 돌아 보는 것만으로도 재미 있습니다! 계약자가 프로젝트를 위해 일을 맡게되었을 때 나는 설계자 / 리더 개발을 맡게되었습니다. 그녀는 저의 직접적인 통제하에 있지 않았지만 팀 작업 목록에서 작업을 배정 받았습니다. 상사는 그녀를 훌륭하다고 찬성했다 (나중에 그녀를 데브 리드로 다시 고용하기도한다). 그녀가 작성하거나 디자인 한 모든 코드가 프로덕션 환경에 적용되지 않았고 팀원이 처음부터 완전히 다시 작성해야한다는 사실은 결코 깨달 지 않았습니다!
— Wolf5370

31

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"으로 바꾸는 것이 실제로 기존 값으로 설정되어 있지 않기 때문에 제안합니다. 그렇지 않으면 좋습니다.
— Jon Skeet

28
DateTime.Now.First ()-먼저 무엇? 샘플 코드에서만 알 수 있습니다.
— mackenir 2018

2
아주 좋아요 그러나 이름이 훨씬 나을 수 있다는 데 동의하십시오.
— bovium

방법이 잘 문서화되어 있으면 Intellisense에서 DateTime.Now.First가 충분히 명확합니다.
— Ryan Lundy

29

gitorious.org/cadenza 는 내가 본 가장 유용한 확장 방법의 전체 라이브러리입니다.


12 가지 기본 확장 방법. 나는 모노 록에 약간 압도적입니다.
— mackenir 2018

(저는 소스 컨트롤을 사용하기 위해 필요한 버전이 아니라 출시 된 버전에 대해 이야기하고 있습니다)
— mackenir

28

프리젠 테이션 형식에 자주 사용하는 것이 있습니다.

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

우와, 포켓몬 예외 처리는 ThreadAbortException 등과 같은 문제를 숨길 것입니다. 구체적인 것을 포착하십시오.
— JBR 윌킨슨

28

로마 숫자에 대한 정보가 있습니다. 자주 사용되지는 않지만 편리합니다. 용법:

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

파이썬 PEP 313은 파이썬에 로마 숫자 리터럴을 포함시키기위한 만우절 농담이었습니다. python.org/dev/peps/pep-0313
— torial

25

크기를 다루는 편리한 방법 :

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

제 생각에는 이것은 코딩 스타일이 실제로 좋지 않습니다. 대신 난독 화 된 논리가 아닌 상수를 사용해야합니다.
— xxbbcc 2019

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's 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에서는 작동하지만 문제가 있습니다 ( msdn.microsoft.com/en-us/library/…의 WPF에 대한 설명 참조 ). 내가 찾은 WPF에 대한 최상의 솔루션은 geekswithblogs.net/lbugnion/archive/2009/09/05/…에 설명되어 있습니다 (정적 속성이므로 실제로 확장 방법으로 작동하지는 않습니다)
— scobi

23

ThrowIfArgumentIsNull은 우리 모두가해야 할 null 검사를 수행하는 좋은 방법입니다.

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 프로젝트 에서이 코드를 사용해도 됩니다.


나도 이것을 좋아하고, 존은 그의 것을 가지고 있고, 우산과 비슷한 것을 사용하고, "ArgumentIs"부분을 떨어 뜨릴 수 있습니다.
— cfeduke

네! 이것은 또한
— 켈프

3
ArgumentNullException-constructor를 1 개의 string-argument와 함께 사용하는 경우 해당 인수는 오류 메시지가 아닌 매개 변수 이름이어야합니다. 따라서 코드는 다음과 같아야합니다. if (obj == null) throw new ArgumentNullException (parameterName);
— Tommy Carlier

이것을 사용 default(T)하고 클래스 요구 사항을 제거합니다.
— Joel Coehoorn

1
@Joel : 기본 형식의 기본값이 아닌 값은 null 값보다 합법적 인 인수입니다. null을 검사하면 기본값을 검사하는 것보다 더 의미가 있습니다. 물론, 나는 Require.ThatArgument(input != null)또는 라고 말함으로써 전체 아이디어를 일반화합니다 Require.ThatArgument(personId > 0). 더 많은 코드를 사용하지 않고 훨씬 유연하며 잘 읽습니다. 오류 메시지 또는 예외 자체를 사용자 정의하려는 경우 기능을 사용하는 추가 재정의가 있습니다.
— StriplingWarrior

22

C #으로 이동할 때 Visual Basic의 With 문을 그리워 하므로 여기로 이동합니다.

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

C #에서 사용하는 방법은 다음과 같습니다.

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

많은 타이핑을 저장합니다!

이것을 다음과 비교하십시오.

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

코드 플렉스 프로젝트에 넣다


4
그냥 추측하지만 T가 구조체라면 어떻게 될지 생각해보십시오.
— Rauhotz

5
또한 가능한 경우 동일한 결과를 얻기 위해 c # 3.0 속성 초기화 구문을 사용합니다.
— Steve

3
@chakrit, 여기 예가 있습니다. 개체를 만들 때만 적용됩니다. Button n = new Button {Name = "Button1", Width = 100, Height = 20, Enabled = true};
— Steve

1
C #의 속성 이니셜 라이저 구문은 이벤트를 지원하지 않기 때문에 많은 이벤트를 연결해야 할 때 유용합니다.
— Gabe

1
새 객체를 만들 때만 사용할 수 있기 때문에 속성 초기화 프로그램 외부에서도 유용합니다. 이 확장은 이전에 작성된 오브젝트에서 작동 할 수 있습니다.
— 브래디 모리츠

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

나는 종종 Capitalize와 함께 사용합니다.

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

코드 플렉스 프로젝트에서 무료로 사용 가능


Capitalize의 Aggregate는 많은 문자열 인스턴스를 생성하기 때문에 성능이 매우 나쁩니다. 대신 word.Substring (1)을 사용하지 않는 이유는 무엇입니까?
— 토마스 레베

17

나는 이것이 도움이되었다는 것을 알았다

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

호출 코드에서 널 검사를 제거합니다. 당신은 지금 할 수 있습니다

MyList.EmptyIfNull().Where(....)

예. 누군가 "Null Object Pattern"을 잊어 버린 경우이 방법을 사용하여 패치 할 수 있습니다. 컬렉션은 null이 아니어야합니다.
— Pavel Hodek

16

지정된 문화권을 사용하여 double을 문자열 형식으로 변환하십시오.

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
당신은 다른 사람이 문제를 반올림거야 통화에 대한 진수를 사용한다
— 앤드류 불락

일반 문자열 대신 매개 변수에 Enum을 사용하는 방법
— Rulas

15

아래는 Rick Strahl의 코드 (및 주석도)를 조정하여 문자열로 변환 할 때마다 바이트 배열 또는 텍스트 파일의 바이트 순서 표시를 추측하거나 읽지 않도록 하는 확장 방법 입니다 .

스 니펫을 사용하면 다음과 같이 간단하게 수행 할 수 있습니다.

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

매우 유용한 방법이지만 확장 방법이어야한다고 생각하지 않습니다.
— 팝 카탈린

텍스트 편집기를 작성하는 경우 아마도 확장 방법이 필요하지만 대부분은 정적 개인 방법에 지나지 않을 것입니다.
— Chris S

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
원하는 경우 int는 thingy.NullOr(t => t.Count)어디에 Count있습니까? default(TReturn)null 대신 반환 해야합니다. 이렇게하면 class제약 조건이 필요하지 않으며 값 유형에도 적용됩니다.
— Thomas Levesque

2
TIn은 클래스 여야합니다. 그렇지 않으면이 전체 확장 메소드가 의미가 없습니다 (값 유형은 널이 될 수 없음). t.Count를 사용한 예제는 위의 확장 방법으로 작동합니다. 다시 한번 살펴봐도 될까요?
— scobi

@ 스콧 : 이것은 일반적인 문제에 유용한 방법입니다. 그러나 TReturn elseValue = default(TReturn).NET 4.0에서만 사용할 수 있다고 생각 합니까? 나는 3.5 SP1을 가지고 있으며 그 구조를 본 적이 없다 (컴파일러도 없음). 방금 메소드 내부로 옮겼습니다. 그러나 한 가지 문제는 메서드에 사용하기 위해 nullable 형식을 개체에 복싱하면 예상치 못한 결과가 발생한다는 것입니다 (예상 한 null 대 0).
— Jim Schubert

@ Jim : default(T)VS2005 이후로 키워드가 있었지만 기본 매개 변수는 새로운 .NET 4 기능이라고 생각합니다. 가장 쉬운 방법은 매개 변수를 사용하는 것과 그렇지 않은 매개 변수를 갖는 것입니다. CLR 2.0과 호환되도록 답변을 업데이트하겠습니다. 권투와 관련하여-그것이 ​​핵심입니다 default. 값 유형의 경우 0으로 초기화 된 데이터이고 모든 참조 유형의 경우 널입니다. 값 형식의 TReturn은 함수 전체에 걸쳐 상자의 상태를 유지해야합니다.
— scobi

@ 스콧 : 내 질문은 루비와 같은 동적 언어에서만 볼 수있는 기본 매개 변수에 관한 것입니다. nullable 형식에 대한 내 요점 x.Value은 반환하면 null (예 : int?null 인 경우) 또는 값 int?이있는 경우 값 을 반환 해야한다는 것 입니다. 객체에 전달되고 상자에 넣어 0질 때 반환 int? x = null하는 것은 이상한 경우입니다. 이 특정 경우에 유창한 nhibernate 및 linfu와 같은 라이브러리에서 nullable 유형에 대한 비슷한 검사를 보았으므로 이전에 제안한대로 클래스 제약 조건을 삭제할 수 있습니다.
— Jim Schubert

14

"Codeplex 프로젝트에 코드를 넣으려면 승인 표시를하십시오."

왜? 이 사이트의 모든 내용은 CC-by-sa-2.5 이므로 Extension overflow 프로젝트를 동일한 라이센스로두면 자유롭게 사용할 수 있습니다.

어쨌든 여기이 질문을 기반으로 한 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);
}

문자열이 이미 IEnumerable <char>을 구현하지 않습니까? 따라서 new String (input.Reverse ());을 반환하면됩니다.
— Iain Galloway

StringBuilder를 사용한 구현이 더 빨라야합니다.
— 코드 InChaos

1
@CodeInChaos stackoverflow.com/questions/228038 의 벤치마킹은 StringBuilder가 느리다는 것을 측정했습니다.
— Michael Stum

네가 옳아. 스레드 안전성 요구 사항 (아마 ToTo가 반환 한 문자열의 불변성을 보장하기 위해)이 StringBuilder를 느리게하는 것처럼 보입니다.
— 코드 InChaos

2
대리모 또는 결합 문자가 발생하지 않기를 바랍니다.
— dalle

14

MySqlDataReader에서 값을 가져 오는 동안 지루한 null 검사에 지쳤습니다.

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와 함께 사용될 수 있습니다.


hangy와 Joe는이 작업을 수행하는 방법에 대한 좋은 의견을 가지고 있으며 다른 맥락에서 비슷한 것을 구현할 수있는 기회가 있었으므로 다른 버전이 있습니다.

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의 확장 방법으로도 작동해야합니다.
— hangy

2
실제로 최대 호환성을 위해 IDataRecord 유형의 "this"매개 변수를 작성하십시오. 이 버전에서는 fieldName 버전이 호출하는 서수를 사용하는 과부하가 있습니다. "GetOrdinal"과 이름 별 조회를 저장합니다.
— Joel Mueller


참조 - 감사 리나 트, 나는 실제로 하나의 일반적인 방법이 아래를 가지고 stackoverflow.com/questions/303287
— 아담 Lassek

as키워드를 사용하여 null을 허용하는 판독기에서 값을 얻을 수 있으므로 이러한 모든 방법이 필요하지 않은 것 같습니다 . 널 병합 ??연산자를 as 연산자와 결합하면 값 유형으로 직접 이동하기 위해 널이 아닌 기본값을 가질 수도 있습니다. 참조 stackoverflow.com/questions/746767/...을
— stevehipwell

14

LINQ는 IComparer를 인수로 구현하는 클래스를 사용하지만 간단한 익명 비교기 함수 전달을 지원하지 않는 OrderBy를 제공한다는 사실을 자극했습니다. 나는 그것을 교정했다.

이 클래스는 비교기 함수에서 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);
    }
}

원하는 경우 코드 플렉스에 넣을 수 있습니다.


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

MvcContrib.FluentHtml 확인
— 아르 니스 Lapsa

이것은 아마도 리터럴과 중복되어야합니다.
— Mark Hurd

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.