C# 3.0から導入された拡張メソッドを使用するにはSystem.Core.dllを参照に追加する必要がある。 これは拡張メソッドを含むコードをコンパイルする際に、System.Core.dllのSystem.Runtime.CompilerServices.ExtensionAttributeを参照するため。
しかし、ExtensionAttributeはSystem.Core.dllで宣言されている必要は無く、コンパイル時に同名の属性が参照できればよいので、ExtensionAttributeを自前で宣言すればSystem.Core.dllを参照することなく拡張メソッドを含むコードをコンパイルできるようになる。
ExtensionAttributeを自前で宣言する場合、
の二点に注意する必要がある。
using System; using System.IO; namespace System.Runtime.CompilerServices { // 拡張メソッドをコンパイルするのに必要となるExtensionAttributeの宣言 [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] public sealed class ExtensionAttribute : Attribute {} } namespace MyExtensions { // 拡張メソッドを含むクラス public static class StringExtensions { public static void WriteTo(this string str, TextWriter writer) { writer.Write(str); } } } namespace Test { // 拡張メソッドを使用するコード using MyExtensions; class MainClass { public static void Main() { "Hello, world!\n".WriteTo(Console.Out); } } }
コンパイル・実行すると次のようにする。 /noconfigを付けないとコンパイラが自動的にSystem.Core.dllへの参照を含めてしまうので注意。
C:\>csc /noconfig ext-method.cs Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1 for Microsoft (R) .NET Framework version 3.5 Copyright (C) Microsoft Corporation. All rights reserved. C:\>ext-method.exe Hello, world!
$ gmcs /noconfig ext-method.cs $ mono ext-method.exe Hello, world!
このようにすることでSystem.Core.dllを参照する必要がなくなるため、拡張メソッドを含むコードでも.NET Framework 2.0をターゲットとしてコンパイルできるようになる。
ちなみに、System.Core.dllを参照に含めてコンパイルすると、System.Core.dllのExtensionAttributeと自前のものが衝突することになるが、警告となるだけでエラーにはならない。
C:\>csc /r:System.Core.dll ext-method.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
warning CS1685: 定義済みの型 'System.Runtime.CompilerServices.ExtensionAttribute' は、グローバル
エイリアスの複数のアセンブリ内で定義されています。'd:\test\ext-method.cs' からの定義を使用してください。
$ gmcs /r:System.Core.dll ext-method.cs ext-method.cs(6,23): warning CS1685: The predefined type `System.Runtime.CompilerServices.ExtensionAttribute' is ambiguous. Using definition from `System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' /usr/local/lib/mono/gac/System.Core/3.5.0.0__b77a5c561934e089/System.Core.dll (Location of the symbol related to previous warning) Compilation succeeded - 1 warning(s)