C #에 확장 속성이 있습니까?
C #에 확장 속성이 있습니까?
예를 들어를 반환 하는 DateTimeFormatInfo
호출에 확장 속성을 추가 할 수 있습니까?ShortDateLongTimeFormat
ShortDatePattern + " " + LongTimePattern
C # 3.0에는 존재하지 않으며 4.0에는 추가되지 않습니다. C #에 필요한 기능 목록에 있으므로 향후 추가 될 수 있습니다.
이 시점에서 최선의 방법은 GetXXX 스타일 확장 메서드입니다.
아니요, 존재하지 않습니다.
나는 C # 팀이 확장 생성자 및 연산자와 함께 한 시점에서 (또는 적어도 Eric Lippert가 그랬던 것처럼) 고려하고 있었다는 것을 알고 있습니다. 그들이 C # 4의 일부가 될 것이라는 증거를 보지 못했습니다.
편집 : 그들은 C # 5에 나타나지 않았고, 2014 년 7 월 현재 C # 6에도있을 것 같지 않습니다.
2012 년 11 월까지 Microsoft C # 컴파일러 팀의 수석 개발자 인 Eric Lippert 는 2009 년 10 월에 이에 대해 블로그를 작성했습니다.
현재로서는 Roslyn 컴파일러에서 기본적으로 지원되지 않습니다.
지금까지 확장 속성은 이전 버전의 C # 표준에 포함될만큼 가치가있는 것으로 간주되지 않았습니다. C # 7 과 C # 8.0 은 이것을 제안 챔피언으로 보았지만 아직 출시되지 않았습니다. 무엇보다도 이미 구현이 있어도 처음부터 바로 만들고 싶어하기 때문입니다.
그러나 그것은 ...
가 확장 회원 에서 항목 C # 7 작업 목록 이 가까운 미래에 지원 될 수 있도록. 확장 속성의 현재 상태는 Github의 관련 항목 아래에서 확인할 수 있습니다 .
그러나 특히 속성과 정적 클래스 또는 필드에 초점을 맞춘 "모든 것을 확장" 하는 훨씬 더 유망한 주제가 있습니다.
또한 해결 방법을 사용할 수 있습니다.
이 문서에 지정된대로 TypeDescriptor
런타임에 속성을 개체 인스턴스에 연결하는 기능을 사용할 수 있습니다 . 그러나 표준 속성의 구문을 사용하지 않습니다. 클래스에 데이터를 저장할 때 확장 메서드의 별칭
과 같은 확장 속성을 정의 할 수있는 가능성을 추가하는 구문 설탕과는 약간 다릅니다 .string Data(this MyClass instance)
string GetData(this MyClass instance)
C # 7이 모든 기능 (속성 및 필드)의 모든 기능을 제공하기를 바라지 만, 그 시점에서 시간이 지나면 알 수 있습니다.
그리고 내일의 소프트웨어가 커뮤니티에서 나올 것이므로 자유롭게 기여하십시오.
업데이트 : 2016 년 8 월
dotnet 팀 이 C # 7.0의 새로운 기능 과 Mads Torgensen 의 의견을 게시했습니다 .
확장 속성 : 우리는 다른 종류의 확장 멤버들과 함께 여름 동안 실험으로 (훌륭한!) 인턴을 구현했습니다. 우리는 이것에 계속 관심이 있지만 큰 변화이며 그만한 가치가 있다는 확신이 필요합니다.
확장 속성 및 기타 멤버는 Roslyn의 향후 릴리스에 포함될 좋은 후보이지만 7.0 버전은 아닐 수 있습니다.
업데이트 : 2017 년 5 월
확장 멤버 도 종료 된 확장 모든 문제의 중복으로종료되었습니다. 주요 논의는 사실 넓은 의미의 유형 확장성에 대한 것이 었습니다. 이 기능은 이제 여기에서 제안으로 추적되며 7.0 마일스톤 에서 제거되었습니다.
업데이트 : 2017 년 8 월-C # 8.0 제안 기능
여전히 제안 된 기능 일 뿐이지 만 이제 구문이 무엇인지 더 명확하게 볼 수 있습니다. 이것은 확장 메서드에 대한 새로운 구문이기도합니다.
public interface IEmployee
{
public decimal Salary { get; set; }
}
public class Employee
{
public decimal Salary { get; set; }
}
public extension MyPersonExtension extends Person : IEmployee
{
private static readonly ConditionalWeakTable<Person, Employee> _employees =
new ConditionalWeakTable<Person, Employee>();
public decimal Salary
{
get
{
// `this` is the instance of Person
return _employees.GetOrCreate(this).Salary;
}
set
{
Employee employee = null;
if (!_employees.TryGetValue(this, out employee)
{
employee = _employees.GetOrCreate(this);
}
employee.Salary = value;
}
}
}
IEmployee person = new Person();
var salary = person.Salary;
Similar to partial classes, but compiled as a separate class/type in a different assembly. Note you will also be able to add static members and operators this way. As mentioned in Mads Torgensen podcast, the extension won't have any state (so it cannot add private instance members to the class) which means you won't be able to add private instance data linked to the instance. The reason invoked for that is it would imply to manage internally dictionaries and it could be difficult (memory management, etc...). For this, you can still use the TypeDescriptor
/ConditionalWeakTable
technique described earlier and with the property extension, hides it under a nice property.
Syntax is still subject to change as implies this issue. For example, extends
could be replaced by for
which some may feel more natural and less java related.
Update December 2018 - Roles, Extensions and static interface members
Extension everything didn't make it to C# 8.0, because of some of drawbacks explained as the end of this GitHub ticket. So, there was an exploration to improve the design. Here, Mads Torgensen explains what are roles and extensions and how they differs:
Roles allow interfaces to be implemented on specific values of a given type. Extensions allow interfaces to be implemented on all values of a given type, within a specific region of code.
It can be seen at a split of previous proposal in two use cases. The new syntax for extension would be like this:
public extension ULongEnumerable of ulong
{
public IEnumerator<byte> GetEnumerator()
{
for (int i = sizeof(ulong); i > 0; i--)
{
yield return unchecked((byte)(this >> (i-1)*8));
}
}
}
then you would be able to do this:
foreach (byte b in 0x_3A_9E_F1_C5_DA_F7_30_16ul)
{
WriteLine($"{e.Current:X}");
}
And for a static interface:
public interface IMonoid<T> where T : IMonoid<T>
{
static T operator +(T t1, T t2);
static T Zero { get; }
}
Add an extension property on int
and treat the int
as IMonoid<int>
:
public extension IntMonoid of int : IMonoid<int>
{
public static int Zero => 0;
}
Update (thanks to @chaost for pointing this update out):
Mads Torgersen: "Extension everything didn’t make it into C# 8.0. It got “caught up”, if you will, in a very exciting debate about the further future of the language, and now we want to make sure we don’t add it in a way that inhibits those future possibilities. Sometimes language design is a very long game!"
Source: comments section in https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/
I stopped counting how many times over the years I opened this question with hopes to have seen this implemented.
Well, finally we can all rejoice! Microsoft is going to introduce this in their upcoming C# 8 release.
So instead of doing this...
public static class IntExtensions
{
public static bool Even(this int value)
{
return value % 2 == 0;
}
}
We'll be finally able to do it like so...
public extension IntExtension extends int
{
public bool Even => this % 2 == 0;
}
Source: https://blog.ndepend.com/c-8-0-features-glimpse-future/
As @Psyonity mentioned, you can use the conditionalWeakTable to add properties to existing objects. Combined with the dynamic ExpandoObject, you could implement dynamic extension properties in a few lines:
using System.Dynamic;
using System.Runtime.CompilerServices;
namespace ExtensionProperties
{
/// <summary>
/// Dynamically associates properies to a random object instance
/// </summary>
/// <example>
/// var jan = new Person("Jan");
///
/// jan.Age = 24; // regular property of the person object;
/// jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
///
/// if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
/// Console.WriteLine("Jan drinks too much");
/// </example>
/// <remarks>
/// If you get 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' you should reference Microsoft.CSharp
/// </remarks>
public static class ObjectExtensions
{
///<summary>Stores extended data for objects</summary>
private static ConditionalWeakTable<object, object> extendedData = new ConditionalWeakTable<object, object>();
/// <summary>
/// Gets a dynamic collection of properties associated with an object instance,
/// with a lifetime scoped to the lifetime of the object
/// </summary>
/// <param name="obj">The object the properties are associated with</param>
/// <returns>A dynamic collection of properties associated with an object instance.</returns>
public static dynamic DynamicProperties(this object obj) => extendedData.GetValue(obj, _ => new ExpandoObject());
}
}
A usage example is in the xml comments:
var jan = new Person("Jan");
jan.Age = 24; // regular property of the person object;
jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
{
Console.WriteLine("Jan drinks too much");
}
jan = null; // NumberOfDrinkingBuddies will also be erased during garbage collection
Because I recently needed this, I looked at the source of the answer in:
c# extend class by adding properties
and created a more dynamic version:
public static class ObjectExtenders
{
static readonly ConditionalWeakTable<object, List<stringObject>> Flags = new ConditionalWeakTable<object, List<stringObject>>();
public static string GetFlags(this object objectItem, string key)
{
return Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value;
}
public static void SetFlags(this object objectItem, string key, string value)
{
if (Flags.GetOrCreateValue(objectItem).Any(x => x.Key == key))
{
Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value = value;
}
else
{
Flags.GetOrCreateValue(objectItem).Add(new stringObject()
{
Key = key,
Value = value
});
}
}
class stringObject
{
public string Key;
public string Value;
}
}
It can probably be improved a lot (naming, dynamic instead of string), I currently use this in CF 3.5 together with a hacky ConditionalWeakTable (https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4)
참고URL : https://stackoverflow.com/questions/619033/does-c-sharp-have-extension-properties
'program tip' 카테고리의 다른 글
나눗셈을 부동 소수점으로 만들려면 어떻게해야합니까? (0) | 2020.09.30 |
---|---|
터미널에서 현재 라인을 삭제 / 삭제하려면 어떻게합니까? (0) | 2020.09.30 |
arr .__ len __ ()이 파이썬에서 배열의 길이를 얻는 데 선호되는 방법입니까? (0) | 2020.09.30 |
어떻게 쉽게 수평 중앙에 (0) | 2020.09.30 |
Bootstrap-테이블 내부에 대한 텍스트 정렬 클래스 (0) | 2020.09.30 |