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.