2016-03-01T00:58:23の更新内容

programming/netfx/obsoletion/index.wiki.txt

current previous
1,880 1,216
~
${smdncms:title,機能の廃止・旧式化}
${smdncms:title,型とメンバの廃止・旧式化}
~
${smdncms:header_title,機能の廃止・旧式化 (Obsolete属性, System.ObsoleteAttribute)}
${smdncms:header_title,型とメンバの廃止・旧式化 (ObsoleteAttribute)}
 
${smdncms:keywords,Obsolete,ObsoleteAttribute}
${smdncms:keywords,Obsolete,ObsoleteAttribute}
 
${smdncms:document_versions,codelang=cs,codelang=vb}
${smdncms:document_versions,codelang=cs,codelang=vb}
 

        

        
~
&msdn(netfx,type,System.ObsoleteAttribute){Obsolete属性};は廃止予定・非推奨となったクラスやメソッドなどに適用する属性で、機能の利用者に対して、機能が廃止予定・非推奨である旨をコンパイラの警告・エラーによって通知することができます。 Obsolete属性による通知はコンパイラによってサポートされるため、機能の利用者はドキュメントの参照なしに機能が古くなった(''obsolete''=&italic{時代遅れ、廃れた};)ことを知ることができます。 Obsolete属性による通知は、Javaにおける``@Deprecated``アノテーションなどに相当する機能と言えます。
&msdn(netfx,type,System.ObsoleteAttribute){Obsolete属性};は古くなったメソッドやクラスなどに対して適用し、それが使用された場合に警告を発することができる属性です。 例えば、互換性維持のために古い実装を残しておきたいが、将来的には廃止する予定のため新たに書くコードでは新しい実装を使うよう警告を出したいといった場合にこの属性が使われます。
+

          
+
Obsolete属性を用いることで、API互換性は維持しつつ、バージョンアップによって廃止予定になった機能の通知や、あるいはより洗練された実装への移行を利用者に対して促すことができます。
 

        

        
 
#relevantdocs
#relevantdocs
 

        

        
 
-[[programming/netfx/attributes]]
-[[programming/netfx/attributes]]
 
-[[programming/netfx/conditional]]
-[[programming/netfx/conditional]]
 
-[[programming/netfx/debugging]]
-[[programming/netfx/debugging]]
+
-[[programming/netfx/classlibrary/0_howtocreate]]
+
-[[programming/netfx/classlibrary/2_xmldoccomments]]
 

        

        
 
#relevantdocs-end
#relevantdocs-end
 

        

        
 
#adunit
#adunit
 

        

        
~
*Obsolete属性の効用
*Obsolete属性の適用
~
**クラスライブラリの利用者側
.NET Frameworkのクラスライブラリでは、既に&msdn(netfx,member,System.Uri.MakeRelative){Uri.MakeRelativeメソッド};や&msdn(netfx,member,System.IO.Path.InvalidPathChars){Path.InvalidPathCharsフィールド};などにObsolete属性が適用されています。 (参照:&msdn(netfx,id,ee461503){互換性のために残されている型};、&msdn(netfx,id,ee471421){互換性のために残されているメンバー};)
+
.NET Frameworkのクラスライブラリやサードパーティ製クラスライブラリの利用者側では、Obsolete属性の存在によってライブラリのクラスやメソッドが廃止予定あるいは非推奨であることを知ることができます。 Obsolete属性が付与されたクラス・メソッドを呼びだそうとしている場合、コンパイラは自動的にObsolete属性の存在を検知し、警告あるいはエラーとして利用者に通知します。
 

        

        
~
例えば、ファイル名に使用できない文字のリストを取得しようとして&msdn(netfx,member,System.IO.Path.InvalidPathChars){Path.InvalidPathCharsフィールド};を参照した場合、コンパイラは次のような警告を通知します。
これらと同様に、自分のコードにもObsolete属性を適用することが出来ます。 以下は、メソッドにObsolete属性を適用する例です。
 

        

        
~
#tabpage(codelang=cs,container-title=Obsoleteなメンバを呼び出そうとしているコード)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
~
using System.IO;
using System.Diagnostics;
 

        

        
~
class Sample {
class Sample
~
  static void Main()
{
-
  [Obsolete("将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。")]
-
  static void OldMethod(string message)
 
  {
  {
~
    var filename = "foo*bar?.txt";
    Console.WriteLine("古いバージョン: " + message);
-
  }
 

        

        
~
    // ファイル名に使用できない文字をアンダーバーに置き換える
  static void NewMethod(string message)
~
    foreach (var c in Path.InvalidPathChars) {
  {
~
      filename = filename.Replace(c, '_');
    Console.WriteLine("新しいバージョン: " + message);
+
    }
+

          
+
    Console.WriteLine(filename);
 
  }
  }
+
}
+
}}
+

          
+
#prompt(コンパイラが出力する警告メッセージ){{
+
test.cs(10,23): warning CS0618: 'System.IO.Path.InvalidPathChars' は古い形式です: 'Please use GetInvalidPathChars or GetInvalidFileNameChars instead.'
+
}}
 

        

        
~
#tabpage(codelang=vb)
  public static void Main()
+
#code{{
+
Imports System
+
Imports System.IO
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim filename As String = "foo*bar?.txt"
+

          
+
    ' ファイル名に使用できない文字をアンダーバーに置き換える
+
    For Each c As Char In Path.InvalidPathChars
+
      filename = filename.Replace(c, "_"c)
+
    Next
+

          
+
    Console.WriteLine(filename)
+
  End Sub
+
End Class
+
}}
+

          
+
#prompt(コンパイラが出力する警告メッセージ){{
+
test.vb(9) : warning BC40000: 'InvalidPathChars' は旧形式です: 'Please use GetInvalidPathChars or GetInvalidFileNameChars instead.'
+
}}
+

          
+
#tabpage-end
+

          
+
このように、ライブラリの利用者はコンパイラから通知される警告によって機能が廃止予定・非推奨であることを知ることができます。 また、警告として通知されるメッセージに代替機能についての情報が含まれていれば、それも得ることができます。 Obsolete属性による警告がない場合、事前にドキュメント等を参照していなければ機能が廃止予定であるか、非推奨となっているかどうかを把握することはできませんが、Obsolete属性が付与されていればコンパイラによる通知によってそれを知ることができます。
+

          
+

          
+

          
+
また、上記の例における警告メッセージでは、Path.InvalidPathCharsの代わりとして&msdn(netfx,member,System.IO.Path.GetInvalidFileNameChars){Path.GetInvalidFileNameCharsメソッド};を用いることが提示されているため、利用者はこれに従うことで非推奨となっている機能を使用しないコードに書き換えることができます。
+

          
+
#tabpage(codelang=cs,container-title=提示された代替メソッドを用いるように書き換えたコード)
+
#code{{
+
using System;
+
using System.IO;
+

          
+
class Sample {
+
  static void Main()
 
  {
  {
~
    var filename = "foo*bar?.txt";
    OldMethod("メソッドを呼び出します");
+

          
+
    // ファイル名に使用できない文字をアンダーバーに置き換える
+
    // (非推奨なPath.InvalidPathCharsの代わりにPath.GetInvalidFileNameChars()を用いる)
+
    foreach (var c in Path.GetInvalidFileNameChars()) {
+
      filename = filename.Replace(c, '_');
+
    }
 

        

        
~
    Console.WriteLine(filename);
    NewMethod("メソッドを呼び出します");
 
  }
  }
 
}
}
 
}}
}}
 
#tabpage(codelang=vb)
#tabpage(codelang=vb)
 
#code{{
#code{{
 
Imports System
Imports System
~
Imports System.IO
Imports System.Diagnostics
 

        

        
 
Class Sample
Class Sample
~
  Shared Sub Main()
  <Obsolete("将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。")> _
~
    Dim filename As String = "foo*bar?.txt"
  Shared Sub OldMethod(ByVal message As String)
-
    Console.WriteLine("古いバージョン: " + message)
-
  End Sub
 

        

        
~
    ' ファイル名に使用できない文字をアンダーバーに置き換える
  Shared Sub NewMethod(ByVal message As String)
~
    ' (非推奨なPath.InvalidPathCharsの代わりにPath.GetInvalidFileNameChars()を用いる)
    Console.WriteLine("新しいバージョン: " + message)
~
    For Each c As Char In Path.GetInvalidFileNameChars()
  End Sub
+
      filename = filename.Replace(c, "_"c)
+
    Next
 

        

        
~
    Console.WriteLine(filename)
  Public Shared Sub Main()
-
    OldMethod("メソッドを呼び出します")
-

          
-
    NewMethod("メソッドを呼び出します")
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
このように廃止予定・非推奨となっていることを知らずに機能を利用しようとしていた場合でも、Obsolete属性によってそれをコンパイル時までに知ることができ、推奨される代替機能へ移行することができます。
このコードをコーディングしているときには、IDE上に次のような警告が表示されます。
-
#image(0.png,nopopup,Sub OldMethod&#x28;message As String&#x29;は旧形式です: '将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。')
 

        

        
~
#remarks
コンパイル時にもこれと同じ警告が発せられます。
+
ファイル名・パス名に使用できない文字に関して詳しくは[[programming/netfx/environment/0_platform#SystemAndPlatform_DirectorySeparatorChar]]を参照してください。
+
#remarks-end
 

        

        
-
#prompt(コンパイル時に出力される警告){{
-
test.cs(20,5): warning CS0618: 'Sample.OldMethod(string)' は古い形式です: '将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。'
-
}}
 

        

        
-
このように、Obsolete属性は互換性のために残してあるような仕様の古くなったコードに対して、使用しないように促す警告を発することができます。
 

        

        
~
Obsolete属性は、IDEによるコード解析機能が使えない場合に、メンバの参照元を検索する用途でも使うことができます。 例えば、次のようにメソッドにObsolete属性をつけることで、そのメソッドを呼び出している個所を警告として表示させることができます。
また、Obsolete属性が適用されているメソッドを使用した場合に、警告ではなくコンパイルエラーとしたい場合には次のようにします。
 

        

        
~
#tabpage(codelang=cs,container-title=Obsolete属性の警告を利用してメソッドを呼び出している個所を検索する)
#tabpage(codelang=cs)
 
#code{{
#code{{
 
using System;
using System;
-
using System.Diagnostics;
 

        

        
~
class Sample {
class Sample
~
  [Obsolete("メソッドを使用している個所")]
{
~
  static void Test()
  [Obsolete("このバージョンは使用しないで下さい。 NewMethodを使用して下さい。", true)]
-
  static void OlderMethod(string message)
 
  {
  {
-
    Console.WriteLine("より古いバージョン: " + message);
 
  }
  }
 

        

        
~
  static void Main()
  [Obsolete("将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。")]
-
  static void OldMethod(string message)
 
  {
  {
~
    Test();
    Console.WriteLine("古いバージョン: " + message);
+
    // test.cs(11,5): warning CS0618: 'Sample.Test()' は古い形式です: 'メソッドを使用している個所'
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+
Class Sample
+
  <Obsolete("メソッドを使用している個所")> _
+
  Shared Sub Test()
+
  End Sub
+

          
+
  Shared Sub Main()
+
    Test()
+
    ' test.vb(9) : warning BC40000: 'Public Shared Sub Test()' は旧形式です: 'メソッドを使用している個所'
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#remarks
+
ユーザー定義の警告・エラーを表示したい場合は、&msdn(netfx,id,963th5x3){#warningディレクティブ};や&msdn(netfx,id,x5hedts0){#errorディレクティブ};を用いることができます。
+
#remarks-end
+

          
+

          
+

          
+
**クラスライブラリの提供者側
+
クラスライブラリの提供者側では、バージョンアップに際して既存の機能を廃止したり、非推奨としたい場合にObsolete属性を用いることができます。 クラスやメソッドに対してObsolete属性を付与することによって、それが廃止予定・非推奨であることを利用者側に通知することができます。
+

          
+
#tabpage(codelang=cs,container-title=Obsolete属性を使って機能が廃止予定・非推奨であることを利用者に通知する)
+
#code{{
+
/* クラスライブラリのコード */
+
using System;
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    // 文字列strに含まれる部分文字列substrの数を返すメソッド
+
    [Obsolete] // <-- Obsolete属性を付与することで廃止予定であることを通知する
+
    public static int Count(string str, string substr)
+
    {
+
      /* 例示のため実装は省略 */
+
      return 0;
+
    }
 
  }
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
' クラスライブラリのコード
+
Imports System
+

          
+
Namespace ClassLibrary
+
  Public Module StringUtils
+
    ' 文字列strに含まれる部分文字列substrの数を返すメソッド
+
    ' (Obsolete属性を付与することで廃止予定であることを通知する)
+
    <Obsolete> _ 
+
    Public Function Count(ByVal str As String, ByVal substr As String) As Integer
+
      ' 例示のため実装は省略
+
      Return 0
+
    End Function
+
  End Module
+
End Namespace
+
}}
+
#tabpage-end
 

        

        
~
このライブラリを利用する側では、このようにObsolete属性が付与されたクラスやメソッドを呼びだそうとした場合、次のようにコンパイラが警告を発します。
  static void NewMethod(string message)
+

          
+
#tabpage(codelang=cs,container-title=Obsolete属性が付与されたメソッドを呼びだそうとすると警告となる)
+
#code{{
+
/* ライブラリ利用者のコード */
+
using System;
+
using ClassLibrary;
+

          
+
class Sample {
+
  static void Main()
 
  {
  {
~
    string text = "foobarbazfoobarbaz";
    Console.WriteLine("新しいバージョン: " + message);
+

          
+
    // ライブラリのメソッドを使って文字列textに含まれる"foo"の数を計上したい
+
    Console.WriteLine(StringUtils.Count(text, "foo"));
 
  }
  }
+
}
+
}}
 

        

        
~
#prompt(コンパイラが出力する警告){{
  public static void Main()
+
test.cs(23,23): warning CS0612: 'ClassLibrary.StringUtils.Count(string, string)' は古い形式です。
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
' ライブラリ利用者のコード
+
Imports System
+
Imports ClassLibrary
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Dim text As String = "foobarbazfoobarbaz"
+

          
+
    ' ライブラリのメソッドを使って文字列textに含まれる"foo"の数を計上したい
+
    Console.WriteLine(StringUtils.Count(text, "foo"))
+
  End Sub
+
End Class
+
}}
+

          
+
#prompt(コンパイラが出力する警告){{
+
test.vb(23) : warning BC40008: 'Public Function Count(str As String, substr As String) As Integer' は旧形式です。
+
}}
+
#tabpage-end
+

          
+

          
+

          
+

          
+
Obsolete属性では、引数&var{message};で警告として出力する文字列を指定することもできるため、単なる廃止予定の通知だけでなく、廃止予定とする理由や、代替となる機能の存在を同時に通知することができます。
+

          
+
#tabpage(codelang=cs,container-title=Obsolete属性を使って旧式化の通知と代替機能への移行を提案する)
+
#code{{
+
/* クラスライブラリのコード */
+
using System;
+

          
+
namespace ClassLibrary {
+
  public static class EnumUtils {
+
    // 文字列strから対応するEnum値への変換を試みるメソッド
+
    [Obsolete(".NET Framework 4以降ではSystem.Enum.TryParse()が提供されています。 System.Enum.TryParse()を使ってください。")]
+
    public static bool TryParse<TEnum>(string str, out TEnum result) where TEnum : struct
+
    {
+
      /* 例示のため実装は省略 */
+
      result = default(TEnum);
+
      return false;
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
' クラスライブラリのコード
+
Imports System
+

          
+
Namespace ClassLibrary
+
  Public Module EnumUtils
+
    ' 文字列strから対応するEnum値への変換を試みるメソッド
+
    <Obsolete(".NET Framework 4以降ではSystem.Enum.TryParse()が提供されています。 System.Enum.TryParse()を使ってください。")> _
+
    Public Function TryParse(Of TEnum As Structure)(ByVal str As String, ByRef result As TEnum) As Boolean
+
      ' 例示のため実装は省略
+
      result = Nothing
+
      Return False
+
    End Function
+
  End Module
+
End Namespace
+
}}
+
#tabpage-end
+

          
+
#tabpage(codelang=cs,container-title=Obsolete属性のメッセージから代替機能の存在を知ることができる)
+
#code{{
+
/* ライブラリ利用者のコード */
+
using System;
+
using ClassLibrary;
+

          
+
class Sample {
+
  static void Main()
 
  {
  {
~
    var str = "Sunday";
    OlderMethod("メソッドを呼び出します");
 

        

        
~
    DayOfWeek d;
    OldMethod("メソッドを呼び出します");
 

        

        
~
    // ここで警告が出力される
    NewMethod("メソッドを呼び出します");
+
    // warning CS0618: 'ClassLibrary.EnumUtils.TryParse<TEnum>(string, out TEnum)' は古い形式です: '.NET Framework 4以降ではSystem.Enum.TryParse()が提供されています。 System.Enum.TryParse()を使ってください。'
+
    if (EnumUtils.TryParse(str, out d))
+
      Console.WriteLine(d);
+

          
+
    // この警告メッセージに従って、利用者は可能であれば代替機能を使ったコードに書き換えることができる
+
    if (Enum.TryParse(str, out d))
+
      Console.WriteLine(d);
 
  }
  }
 
}
}
 
}}
}}
 
#tabpage(codelang=vb)
#tabpage(codelang=vb)
 
#code{{
#code{{
+
' ライブラリ利用者のコード
 
Imports System
Imports System
~
Imports ClassLibrary
Imports System.Diagnostics
 

        

        
 
Class Sample
Class Sample
~
  Shared Sub Main()
  <Obsolete("このバージョンは使用しないで下さい。 NewMethodを使用して下さい。", True)> _
~
    Dim str As String = "Sunday"
  Shared Sub OlderMethod(ByVal message As String)
~
    Dim d As DayOfWeek
    Console.WriteLine("より古いバージョン: " + message)
+

          
+
    ' ここで警告が出力される
+
    ' warning CS0618: 'warning BC40000: 'Public Function TryParse(Of TEnum As Structure)(str As String, ByRef result As TEnum) As Boolean' は旧形式です: '.NET Framework 4以降ではSystem.Enum.TryParse()が提供されています。 System.Enum.TryParse()を使ってください。'
+
    If EnumUtils.TryParse(str, d) Then
+
      Console.WriteLine(d)
+
    End If
+

          
+
    ' この警告メッセージに従って、利用者は可能であれば代替機能を使ったコードに書き換えることができる
+
    If [Enum].TryParse(str, d) Then
+
      Console.WriteLine(d)
+
    End If
 
  End Sub
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
また、Obsolete属性の引数&var{error};に``true``を指定すれば、Obsoleteとなったメンバの使用を警告ではなく''エラーとして通知''させるようにすることができます。 利用者側では、このようなObsolete属性が付与されたメンバを呼び出そうとするとコンパイルエラーとなり、''一切使用することができなくなります''。 機能や実装に問題があり、機能へのアクセスや利用を一切禁止したいような場合には、Obsolete属性を使って呼び出しをコンパイルエラーとすることができます。
  <Obsolete("将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。")> _
-
  Shared Sub OldMethod(ByVal message As String)
-
    Console.WriteLine("古いバージョン: " + message)
-
  End Sub
 

        

        
~
#tabpage(codelang=cs,container-title=Obsolete属性を用いて機能へのアクセスをエラー扱いにする)
  Shared Sub NewMethod(ByVal message As String)
~
#code{{
    Console.WriteLine("新しいバージョン: " + message)
~
/* クラスライブラリのコード */
  End Sub
+
using System;
+

          
+
namespace ClassLibrary {
+
  // POPを使ってメールサーバーにアクセスするクライアント
+
  public class PopClient {
+
    // APOPによるログインを試行するメソッド
+
    [Obsolete(error: true, message: "APOPによるログインには脆弱性が指摘されています。 使用しないでください。 (詳細: http://www.ipa.go.jp/security/vuln/200704_APOP.html)")]
+
    public void LoginApop(string user, string pass)
+
    {
+
      /* 例示のため実装は省略 */
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
' クラスライブラリのコード
+
Imports System
+

          
+
Namespace ClassLibrary
+
  ' POPを使ってメールサーバーにアクセスするクライアント
+
  Public Class PopClient
+
    ' APOPによるログインを試行するメソッド
+
    <Obsolete("APOPによるログインには脆弱性が指摘されています。 使用しないでください。 (詳細: http://www.ipa.go.jp/security/vuln/200704_APOP.html)", True)> _
+
    Public Sub LoginApop(ByVal user As String, ByVal pass As String)
+
      ' 例示のため実装は省略
+
    End Sub
+
  End Class
+
End Namespace
+
}}
+
#tabpage-end
+

          
+
#tabpage(codelang=cs,container-title=Obsolete属性によって機能のアクセスがコンパイルエラーとなる)
+
#code{{
+
/* ライブラリ利用者のコード */
+
using System;
+
using ClassLibrary;
 

        

        
~
class Sample {
  Public Shared Sub Main()
~
  static void Main()
    OlderMethod("メソッドを呼び出します")
+
  {
+
    var c = new PopClient();
+

          
+
    // この呼び出しはエラーとなり、コンパイルに失敗する
+
    // error CS0619: 'ClassLibrary.PopClient.LoginApop(string, string)' は古い形式です: 'APOPによるログインには脆弱性が指摘されています。 使用しないでください。 (詳細: http://www.ipa.go.jp/security/vuln/200704_APOP.html)'
+
    c.LoginApop("user", "pass");
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
' ライブラリ利用者のコード
+
Imports System
+
Imports ClassLibrary
 

        

        
~
Class Sample
    OldMethod("メソッドを呼び出します")
+
  Shared Sub Main()
+
    Dim c As New PopClient()
 

        

        
~
    ' この呼び出しはエラーとなり、コンパイルに失敗する
    NewMethod("メソッドを呼び出します")
+
    ' error BC30668: 'Public Sub LoginApop(user As String, pass As String)' は旧形式です: 'APOPによるログインには脆弱性が指摘されています。 使用しないでください。 (詳細: http://www.ipa.go.jp/security/vuln/200704_APOP.html)'
+
    c.LoginApop("user", "pass")
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~
廃止予定ではなく、廃止済みであることを通知したい場合にも、エラーとすることによって利用者に通知できます。
OlderMethodで指定しているObsolete属性のように、コンストラクタの二つ目の引数にtrueを指定します。 このようにすると、このメソッドを使用しようとした場合は警告ではなくエラーとなり、このメソッドを使用したコードをコンパイルしようとするとコンパイルエラーが発生します。
 

        

        
~
#tabpage(codelang=cs,container-title=Obsolete属性を用いて機能が廃止済みであることを通知する)
#prompt(コンパイル時に出力されるエラー・警告){{
~
#code{{
test.cs(25,5): error CS0619: 'Sample.OlderMethod(string)' は古い形式です: 'このバージョンは使用しないで下さい。 NewMethodを使用して下さい。'
~
/* クラスライブラリのコード */
test.cs(27,5): warning CS0618: 'Sample.OldMethod(string)' は古い形式です: '将来サポートされなくなる可能性があります。 NewMethodを使用して下さい。'
+
using System;
+

          
+
namespace ClassLibrary {
+
  // POPを使ってメールサーバーにアクセスするクライアント
+
  public class PopClient {
+
    // APOPによるログインを試行するメソッド
+
    [Obsolete(error: true, message: "APOPによるログインには脆弱性が指摘されたため、廃止しました。 代わりにPopClient.LoginSaslMD5()などを使用してください。")]
+
    public void LoginApop(string user, string pass)
+
    {
+
      throw new NotSupportedException();
+
    }
+

          
+
    // SASL MD5を使ったログインを試行するメソッド
+
    public void LoginSaslMD5(string user, string pass)
+
    {
+
      /* 例示のため実装は省略 */
+
    }
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
' クラスライブラリのコード
+
Imports System
+

          
+
Namespace ClassLibrary
+
  ' POPを使ってメールサーバーにアクセスするクライアント
+
  Public Class PopClient
+
    ' APOPによるログインを試行するメソッド
+
    <Obsolete("APOPによるログインには脆弱性が指摘されたため、廃止しました。 代わりにPopClient.LoginSaslMD5()などを使用してください。", True)> _
+
    Public Sub LoginApop(ByVal user As String, ByVal pass As String)
+
      Throw New NotSupportedException()
+
    End Sub
+

          
+
    ' SASL MD5を使ったログインを試行するメソッド
+
    Public Sub LoginSaslMD5(ByVal user As String, ByVal pass As String)
+
      ' 例示のため実装は省略
+
    End Sub
+
  End Class
+
End Namespace
 
}}
}}
+
#tabpage-end
+

          
 

        

        
-
#image(1.png,nopopup,IDE上に表示されたコンパイルエラー・警告)
 

        

        
-
ここまでの例ではメソッドに対してObsolete属性を適用してきましたが、クラスや構造体など(アセンブリ、モジュール、パラメータ、戻り値以外)に対して適用することもできます。 次の例は、構造体に対してObsolete属性を適用したものです。
 

        

        
~
このほかにも、ライブラリ実装の都合あるいは経緯上、ライブラリ外に公開せざるを得ない(``public``な)クラスやメソッドが存在する場合にもObsolete属性を用いることができます。 例えば過去のバージョンで公開していた機能を安全な形に隠蔽するようにした場合や、デザイナや外部ツールなどから参照されるような利用者が直接使用しない機能などが考えられます。
#tabpage(codelang=cs)
+

          
+
ドキュメント等に記載されないようなクラスやメソッドの場合でも、それが``public``であれば入力候補等で表示されてしまいます。 このようなメンバにObsolete属性を付与しておくことによって、利用者が誤って使用してしまうことや、意図的に使用した場合の結果が保証できないことを通知することができます。
+

          
+
#tabpage(codelang=cs,container-title=Obsolete属性を使って「非公式な」メンバの参照を警告する)
 
#code{{
#code{{
 
using System;
using System;
-
using System.Diagnostics;
-
using System.Drawing;
 

        

        
~
namespace ClassLibrary {
[Obsolete("System.Drawing.Colorを使用して下さい。")]
~
  public static class Infrastructure {
struct ARGB
~
    // 実装上の都合でpublicとせざるを得ないメソッド
{
~
    [Obsolete("ライブラリの初期化に必要なメソッドです。 ライブラリ外から呼び出した場合は現在の状態が変更されるため呼び出さないでください。")]
  byte R;
~
    public static void Initialize()
  byte G;
~
    {
  byte B;
~
    }
  byte A;
+

          
+
    // 実装上の都合でpublicとせざるを得ないプロパティ
+
    [Obsolete("ライブラリの状態取得に必要なプロパティです。 このプロパティの情報を前提としたコードを記述しないでください。")]
+
    public static bool IsInitialize {
+
      get { return true; }
+
    }
+
  }
 
}
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+
Namespace ClassLibrary
+
  Public Module Infrastructure
+
    ' 実装上の都合でPublicとせざるを得ないメソッド
+
    <Obsolete("ライブラリの初期化に必要なメソッドです。 ライブラリ外から呼び出した場合は現在の状態が変更されるため呼び出さないでください。")> _
+
    Public Sub Initialize()
+
    End Sub
+

          
+
    ' 実装上の都合でPublicとせざるを得ないプロパティ
+
    <Obsolete("ライブラリの状態取得に必要なプロパティです。 このプロパティの情報を前提としたコードを記述しないでください。")> _
+
    Public ReadOnly Property IsInitialize As Boolean
+
      Get
+
        Return True
+
      End Get
+
    End Property
+
  End Module
+
End Namespace
+
}}
+
#tabpage-end
+

          
+
#remarks
+
.NET Frameworkのクラスライブラリにおいてもこのようなメンバが存在します。 例えば&msdn(netfx,member,System.Net.WebClient.AllowReadStreamBuffering){WebClient.AllowReadStreamBufferingプロパティ};などはObsolete属性が付与されていて、ユーザーが直接使用することを想定としたものではないことが通知されるようになっています。
+
#remarks-end
+

          
+
#remarks
+
メンバの存在をデバッガやデザイナから''見えなく''する目的には、&msdn(netfx,type,System.Diagnostics.DebuggerHiddenAttribute){DebuggerHidden属性};や&msdn(netfx,type,System.Diagnostics.DebuggerNonUserCodeAttribute){DebuggerNonUserCode属性};などを用いることができます。 詳しくは[[programming/netfx/debugging]]を参照してください、
+
#remarks-end
+

          
+

          
+

          
+
*.NET Frameworkクラスライブラリの非推奨な型・メンバ
+
.NET Frameworkのクラスライブラリでは、既に&msdn(netfx,member,System.Uri.MakeRelative){Uri.MakeRelativeメソッド};や&msdn(netfx,member,System.IO.Path.InvalidPathChars){Path.InvalidPathCharsフィールド};などにObsolete属性が適用され、非推奨となっています。 このほかにも、ドキュメントの以下のページにて非推奨となった型・メンバの一覧が掲載されています。
+

          
+
-&msdn(netfx,id,ee461502){.NET Framework クラス ライブラリの互換性のために残されている機能};
+
--&msdn(netfx,id,hh419162){.NET Framework 4.5 で互換性のために残されている型};
+
--&msdn(netfx,id,hh419161){.NET Framework 4.5 で互換性のために残されているメンバー};
+
--&msdn(netfx,id,ee461503){.NET Framework 4 で互換性のために残されている型};
+
--&msdn(netfx,id,ee471421){.NET Framework 4 で互換性のために残されているメンバー};
 

        

        
~

          
class Sample
~

          
{
~
*Obsolete属性を適用できる個所
  public static void Main()
+
Obsolete属性は、次のようにクラス・構造体・インターフェイスなどのすべての型、およびメソッド・プロパティ・イベント・フィールドなどのメンバに対して適用することができます。 また、``public``ではない型・メンバにも適用することができます。 アセンブリ全体をObsoleteにすることはできません。
+

          
+
#tabpage(codelang=cs,container-title=様々な要素にObsolete属性を付与する)
+
#code{{
+
using System;
+

          
+
// アセンブリ全体には適用できない
+
//[assembly: Obsolete]
+

          
+
namespace ClassLibrary {
+
  [Obsolete]
+
  public struct S { }
+

          
+
  [Obsolete]
+
  public interface I {}
+

          
+
  [Obsolete]
+
  public class C {
+

          
+
    [Obsolete]
+
    void Method()
+
    {
+
    }
+

          
+
    [Obsolete]
+
    bool Property {
+
      get; set;
+
    }
+

          
+
    [Obsolete]
+
    event EventHandler Event;
+

          
+
    [Obsolete]
+
    int Field;
+
  }
+
}
+
}}
+
#tabpage(codelang=vb)
+
#code{{
+
Imports System
+

          
+
' アセンブリ全体には適用できない
+
'<Assembly: Obsolete>
+

          
+
Namespace ClassLibrary
+
  <Obsolete> _
+
  Public Structure S
+
  End Structure
+

          
+
  <Obsolete> _
+
  Public Interface I
+
  End Interface
+

          
+
  <Obsolete> _
+
  Public Class C
+
    <Obsolete> _
+
    Sub Method()
+
    End Sub
+

          
+
    <Obsolete> _
+
    Property P As Boolean
+
      Get
+
        Return False
+
      End Get
+
      Set
+
      End Set
+
    End Property
+

          
+
    <Obsolete> _
+
    Event E As EventHandler
+

          
+
    <Obsolete> _
+
    Dim Filed As Integer
+
  End Class
+
End Namespace
+
}}
+
#tabpage-end
+

          
+

          
+

          
+
型全体に対してObsolete属性を適用した場合、その型のすべてのメンバにObsolete属性が適用された状態と同じになります。 型全体をObsoleteにして、特定のメンバのみを非Obsoleteにするといったことはできません。
+

          
+
#tabpage(codelang=cs,container-title=Obsoleteな型のメンバを呼び出すと警告となる)
+
#code{{
+
using System;
+

          
+
// クラス全体をObsoleteにする
+
[Obsolete]
+
static class Utils {
+
  // 必然的にこのメソッドもObsoleteとなる
+
  public static void UtilMethod()
+
  {
+
  }
+
}
+

          
+
class Sample {
+
  static void Main()
 
  {
  {
~
    // Obsoleteな型のメンバを参照しようとすると警告となる
    ARGB col1;
~
    // warning CS0612: 'Utils' は古い形式です。
    Color col2;
+
    Utils.UtilMethod();
 
  }
  }
 
}
}
 
}}
}}
 
#tabpage(codelang=vb)
#tabpage(codelang=vb)
 
#code{{
#code{{
 
Imports System
Imports System
-
Imports System.Diagnostics
-
Imports System.Drawing
 

        

        
~
' モジュール全体をObsoleteにする
<Obsolete("System.Drawing.Colorを使用して下さい。")> _
~
<Obsolete> _
Structure ARGB
~
Module Utils
  Dim R As Byte
~
  ' 必然的にこのメソッドもObsoleteとなる
  Dim G As Byte
~
  Public Sub UtilMethod()
  Dim B As Byte
~
  End Sub
  Dim A As Byte
~
End Module
End Structure
 

        

        
 
Class Sample
Class Sample
~
  Shared Sub Main()
  Public Shared Sub Main()
~
    ' Obsoleteな型のメンバを参照しようとすると警告となる
    Dim col1 As ARGB
~
    ' warning BC40008: 'Utils' は旧形式です。
    Dim col2 As Color
+
    Utils.UtilMethod()
 
  End Sub
  End Sub
 
End Class
End Class
 
}}
}}
 
#tabpage-end
#tabpage-end
 

        

        
~

          
#prompt(コンパイル時に出力される警告){{
~

          
test.cs(18,5): warning CS0618: 'ARGB' は古い形式です: 'System.Drawing.Colorを使用して下さい。'
+
*機能提供開始から廃止までとObsolete属性 [#deprecate_library_api]
+
ここでは、クラスライブラリで一度提供を開始したメソッドをObsoleteとし、最終的に廃止するまでをリリース毎に考えていきます。 機能の廃止や置き換えに関するリリースポリシーの一例としてご覧ください。
+

          
+
まず、最初のリリースでは以下のようにメソッドを提供したとします。
+

          
+
#code(cs,クラスライブラリ・バージョン1){{
+
using System;
+

          
+
[assembly: System.Reflection.AssemblyVersion("1.0.*")]
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    public static string Reverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+
  }
+
}
 
}}
}}
 

        

        
-
IDE上には次のような警告が表示されます。
 

        

        
~

          
#image(2.png,nopopup,ARGBは旧形式です: 'System.Drawing.Colorを使用して下さい。')
+
実装に問題がある、より洗練された実装を提供するなどの理由により、今後のリリースではこのメソッドの利用を推奨しないことになったとします。 これに従い、メソッドにObsolete属性を追加することによって利用者にその旨を通知します。 同時に、代替となる新しいメソッドも用意します。
+

          
+
#code(cs,クラスライブラリ・バージョン2){{
+
[assembly: System.Reflection.AssemblyVersion("2.0.*")]
+

          
+
using System;
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <remarks>このメソッドはサロゲートペアを含む文字列を正しく処理できません。</remarks>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    [Obsolete("このメソッドは推奨されません。 文字列がサロゲートペアを含む場合はCodePointWiseReverse()を使用してください。")]
+
    public static string Reverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+

          
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    /// <remarks>このメソッドはサロゲートペアを含む文字列でも正しく処理します。</remarks>
+
    public static string CodePointWiseReverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+
  }
+
}
+
}}
+

          
+
このとき、旧式メソッドと動作が変わらない代替メソッドを提供できる場合や、動作が変わっても問題ないと判断する場合は、旧式メソッドから代替メソッドを呼び出すようにして機能を完全に置き換えてしまうこともできます。
+

          
+
#code(cs,クラスライブラリ・バージョン2){{
+
using System;
+

          
+
[assembly: System.Reflection.AssemblyVersion("2.0.*")]
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    [Obsolete("このメソッドは廃止予定です。 CodePointWiseReverse()を使用してください。")]
+
    public static string Reverse(string str)
+
    {
+
      // 代替メソッドを使用する実装にする
+
      return CodePointWiseReverse(str);
+
    }
+

          
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    /// <remarks>このメソッドはサロゲートペアを含む文字列でも正しく処理します。</remarks>
+
    public static string CodePointWiseReverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+
  }
+
}
+
}}
+

          
+

          
+

          
+
次のリリースでは、これまでに廃止予定としたメソッドを廃止することになったとします。 これに従いObsolete属性のメッセージを変更し、またこれまで警告としていたメソッドの利用を、&var{error}; = ``true``を追加してエラーとして扱うように変更します。
+

          
+
#code(cs,クラスライブラリ・バージョン3){{
+
using System;
+

          
+
[assembly: System.Reflection.AssemblyVersion("3.0.*")]
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <remarks>このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。</remarks>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    [Obsolete(error: true, message: "このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。")]
+
    public static string Reverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+

          
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    /// <remarks>このメソッドはサロゲートペアを含む文字列でも正しく処理します。</remarks>
+
    public static string CodePointWiseReverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+
  }
+
}
+
}}
+

          
+
この時点で、利用者は旧式のメソッドを使うことができなくなり、代替メソッドを使用しなければならなくなります。
+

          
+
#remarks
+
Obsolete属性による警告・エラーは、''コンパイル時にのみ''発せられます。 従って、ライブラリを参照するコンパイル済みのコードがある場合、ライブラリ側でObsolete属性が警告からエラーに変わったとしても、コンパイル済みコードの実行には影響しません。 再コンパイルする時点で初めてエラーとして通知されます。
+

          
+
実行可能ファイルを再コンパイルせず、コンパイル済みのライブラリだけを置き換えてバージョンアップするようなシナリオの場合、Obsolete属性の&var{error};パラメータが``false``から``true``に変わっても、''引き続き旧式のメソッドが呼び出される''ことになります。
+
#remarks-end
+

          
+
旧式メソッドの廃止に伴い、実装も削除すると判断した場合は、次のように例外&msdn(netfx,type,System.NotSupportedException){NotSupportedException};をスローするようにすることもできます。
+

          
+
#code(cs,クラスライブラリ・バージョン3){{
+
using System;
+

          
+
[assembly: System.Reflection.AssemblyVersion("3.0.*")]
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <remarks>このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。</remarks>
+
    /// <exception cref="NotSupportedException">このメソッドを呼び出した場合にスローされます。</exception>
+
    [Obsolete(error: true, message: "このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。")]
+
    public static string Reverse(string str)
+
    {
+
      throw new NotSupportedException("このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。");
+
    }
+

          
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    /// <remarks>このメソッドはサロゲートペアを含む文字列でも正しく処理します。</remarks>
+
    public static string CodePointWiseReverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+
  }
+
}
+
}}
+

          
+
&var{error};パラメータを``true``にした時点で、新たにコンパイルするコードではエラーとなり、利用できない状態になります。 しかし、コンパイル済みのコードからは依然として呼び出し自体は可能であるため、そういった呼び出しも禁止したい場合はこのように例外をスローするようにします。
+

          
+
#remarks
+
実装されていない旨を強調するために、NotSupportedExceptionではなく&msdn(netfx,type,System.NotImplementedException){NotImplementedException};をスローすることも考えられます。 ただ、NotImplementedExceptionでは今後実装される可能性のニュアンスを含むため、完全に廃止された機能の場合はどちらの例外がより妥当かどうかは判断が分かれます。
+

          
+
.NET Frameworkでは、ObsoleteExceptionやDeprecatedExceptionといったようなこの状況に適した例外クラスは用意されていません。 十分な必要性があるなら、NotSupportedExceptionあるいはNotImplementedExceptionを継承してこのような例外クラスを作成し、スローするということも考えられます。
+
#remarks-end
+

          
+

          
+

          
+
ここまでの時点では、機能自体は廃止したものの、クラスライブラリのAPI互換性は維持されています。
+

          
+
クラスライブラリのAPI互換性を破壊するようなリリースを行っても問題ないと判断する場合は、次のように完全にメソッド自体を削除した上でリリースすることもできます。
+

          
+
#code(cs,クラスライブラリ・バージョン4){{
+
using System;
+

          
+
[assembly: System.Reflection.AssemblyVersion("4.0.*")]
+

          
+
namespace ClassLibrary {
+
  public static class StringUtils {
+
    /*
+
     * 廃止したメソッドを完全に削除する(API互換性は失われる)
+
     *
+
    [Obsolete(error: true, message: "このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。")]
+
    public static string Reverse(string str)
+
    {
+
      throw new NotSupportedException("このメソッドは廃止されました。 CodePointWiseReverse()を使用してください。");
+
    }
+
    */
+

          
+
    /// <summary>文字列の並びを逆転した結果を返します。</summary>
+
    /// <returns><paramref name="str"/>の文字の並びを逆転した<see cref="System.String"/>を返します。</returns>
+
    /// <remarks>このメソッドはサロゲートペアを含む文字列でも正しく処理します。</remarks>
+
    public static string CodePointWiseReverse(string str)
+
    {
+
      /* 例示のため実装は省略 */
+
      return string.Empty;
+
    }
+
  }
+
}
+
}}
+

          
+
#remarks
+
ここまでの例でライブラリのバージョンを明記するために用いた属性&msdn(netfx,type,System.Reflection.AssemblyVersionAttribute){AssemblyVersion};については[[programming/netfx/tips/get_assembly_version_info]]などを参照してください。
+
#remarks-end
+

          
+
*Obsolete属性とXMLドキュメントコメント [#documentation_of_deprecated_api]
+
C#やVB.NETでは、[[XMLドキュメントコメント>programming/netfx/classlibrary/2_xmldoccomments]]によってメソッドの機能・動作・引数と戻り値の説明などを記述することができます。 しかし、Javadocにおける``@deprecatedタグ``のような廃止予定・非推奨となった旨を記述する要素、例えば``<obsolete>``や``<deprecated>``のような要素は定義されていません。 そのため``<summary>``要素や``<remarks>``要素として記述する必要があります。
+

          
+
なお、&msdn(netfx,id,fzdc5d5k){Javadoc コメントと等価な XML ドキュメント};および&msdn(netfx,id,dn387587){<deprecated> (JavaScript)};によれば、J#では``<obsolete>``要素、JavaScriptでは``<deprecated>``要素が定義されています。 C#やVB.NETでもこういった要素を使った記述自体は行えますが、ドキュメントによって定義されていない要素のため、ビューアーやドキュメントジェネレータが対応していない限り、適切に表示されるとは限りません。
+

          
+
この他、XMLドキュメントコメントで用いることができる要素と意味についての詳細は[[programming/netfx/classlibrary/2_xmldoccomments#document_elements]]を参照してください。
+

          
+