Класс System.NotSupportedException

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

NotSupportedException указывает, что реализация не существует для вызываемого метода или свойства.

NotSupportedException использует HRESULT COR_E_NOTSUPPORTED, который имеет значение 0x80131515.

Список начальных значений свойств для экземпляра NotSupportedException, см. в разделе NotSupportedException конструкторы.

Создание исключения NotSupportedException

Вы можете вызвать NotSupportedException исключение в следующих случаях:

  • Вы реализуете интерфейс общего назначения и количество методов не имеют понятной реализации. Например, если вы создаете тип даты и времени, реализующего IConvertible интерфейс, вы создадите NotSupportedException исключение для большинства преобразований.

  • Вы унаследовали от абстрактного класса, требующего переопределения ряда методов. Однако вы готовы предоставить реализацию только для подмножества этих элементов. Для методов, которые вы решили не реализовать, можно выбрать исключение NotSupportedException.

  • Вы определяете тип общего назначения с состоянием, которое позволяет выполнять операции условно. Например, тип может быть только для чтения или записи. В этом случае:

    • Если объект доступен только для чтения, попытка назначить значения свойствам экземпляра или вызывать методы, изменяющие состояние экземпляра, должны вызывать NotSupportedException исключение.

    • Необходимо реализовать свойство, возвращающее значение, указывающее Boolean , доступна ли определенная функциональность. Например, для типа, который может быть доступным только для чтения или записи, можно реализовать IsReadOnly свойство, указывающее, доступен ли набор методов чтения и записи или недоступен.

Обработка исключения NotSupportedException

Исключение NotSupportedException указывает, что метод не имеет реализации и не должен вызывать его. Не следует обрабатывать исключение. Вместо этого, что следует сделать, зависит от причины исключения: отсутствует ли реализация или вызов члена не согласуется с целью объекта (например, вызов FileStream.Write метода только для чтения FileStream ).

Реализация не была предоставлена, так как операция не может быть выполнена значимым образом. Это обычное исключение при вызове методов объекта, предоставляющего реализации методов абстрактного базового класса или реализующего интерфейс общего назначения, и метод не имеет понятной реализации.

Например, Convert класс реализует IConvertible интерфейс, что означает, что он должен включать метод для преобразования каждого примитивного типа в любой другой примитивный тип. Однако многие из этих преобразований недоступны. В результате вызов Convert.ToBoolean(DateTime) метода, например, вызывает NotSupportedException исключение, поскольку преобразование между DateTime значением и Boolean значением невозможно.

Чтобы исключить исключение, следует исключить вызов метода.

Вызов метода не поддерживается, учитывая состояние объекта. Вы пытаетесь вызвать члена, функциональность которого недоступна из-за состояния объекта. Исключение можно исключить одним из трех способов:

  • Вы знаете состояние объекта заранее, но вы вызвали неподдерживаемый метод или свойство. В этом случае вызов члена является ошибкой, и ее можно устранить.

  • Вы знаете состояние объекта заранее (обычно потому, что код создал его), но объект настроен неправильно. В следующем примере показана эта проблема. Он создает объект только для FileStream чтения, а затем пытается написать в него.

    using System;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    
    public class Example
    {
        public static async Task Main()
        {
            Encoding enc = Encoding.Unicode;
            String value = "This is a string to persist.";
            Byte[] bytes = enc.GetBytes(value);
    
            FileStream fs = new FileStream(@".\TestFile.dat",
                                           FileMode.Open,
                                           FileAccess.Read);
            Task t = fs.WriteAsync(enc.GetPreamble(), 0, enc.GetPreamble().Length);
            Task t2 = t.ContinueWith((a) => fs.WriteAsync(bytes, 0, bytes.Length));
            await t2;
            fs.Close();
        }
    }
    // The example displays the following output:
    //    Unhandled Exception: System.NotSupportedException: Stream does not support writing.
    //       at System.IO.Stream.BeginWriteInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state
    //    , Boolean serializeAsynchronously)
    //       at System.IO.FileStream.BeginWrite(Byte[] array, Int32 offset, Int32 numBytes, AsyncCallback userCallback, Object sta
    //    teObject)
    //       at System.IO.Stream.<>c.<BeginEndWriteAsync>b__53_0(Stream stream, ReadWriteParameters args, AsyncCallback callback,
    //    Object state)
    //       at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func`5 beginMet
    //    hod, Func`3 endMethod)
    //       at System.IO.Stream.BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at System.IO.FileStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    //       at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at Example.Main()
    
    open System.IO
    open System.Text
    
    let main = task {
        let enc = Encoding.Unicode
        let value = "This is a string to persist."
        let bytes  = enc.GetBytes value
    
        let fs = new FileStream(@".\TestFile.dat", FileMode.Open, FileAccess.Read)
        let t = fs.WriteAsync(enc.GetPreamble(), 0, enc.GetPreamble().Length)
        let t2 = t.ContinueWith(fun a -> fs.WriteAsync(bytes, 0, bytes.Length))
        let! _ = t2
        fs.Close()
    }
    main.Wait()
    
    // The example displays the following output:
    //    Unhandled Exception: System.NotSupportedException: Stream does not support writing.
    //       at System.IO.Stream.BeginWriteInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state
    //    , Boolean serializeAsynchronously)
    //       at System.IO.FileStream.BeginWrite(Byte[] array, Int32 offset, Int32 numBytes, AsyncCallback userCallback, Object sta
    //    teObject)
    //       at System.IO.Stream.<>c.<BeginEndWriteAsync>b__53_0(Stream stream, ReadWriteParameters args, AsyncCallback callback,
    //    Object state)
    //       at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func`5 beginMet
    //    hod, Func`3 endMethod)
    //       at System.IO.Stream.BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at System.IO.FileStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    //       at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at <StartupCode:fs>.main()
    
    Imports System.IO
    Imports System.Text
    Imports System.Threading.Tasks
    
    Module Example
       Public Sub Main()
          Dim enc As Encoding = Encoding.Unicode
          Dim value As String = "This is a string to persist."
          Dim bytes() As Byte = enc.GetBytes(value)
    
          Dim fs As New FileStream(".\TestFile.dat", 
                                   FileMode.Open,
                                   FileAccess.Read)
          Dim t As Task = fs.WriteAsync(enc.GetPreamble(), 0, enc.GetPreamble().Length)
          Dim t2 As Task = t.ContinueWith(Sub(a) fs.WriteAsync(bytes, 0, bytes.Length)) 
          t2.Wait()
          fs.Close()
       End Sub
    End Module
    ' The example displays the following output:
    '    Unhandled Exception: System.NotSupportedException: Stream does not support writing.
    '       at System.IO.Stream.BeginWriteInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state
    '    , Boolean serializeAsynchronously)
    '       at System.IO.FileStream.BeginWrite(Byte[] array, Int32 offset, Int32 numBytes, AsyncCallback userCallback, Object sta
    '    teObject)
    '       at System.IO.Stream.<>c.<BeginEndWriteAsync>b__53_0(Stream stream, ReadWriteParameters args, AsyncCallback callback,
    '    Object state)
    '       at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func`5 beginMet
    '    hod, Func`3 endMethod)
    '       at System.IO.Stream.BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count)
    '       at System.IO.FileStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    '       at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
    '       at Example.Main()
    

    Ycan устраняет исключение, гарантируя, что экземпляр объекта поддерживает функциональность, которую вы планируете. В следующем примере рассматривается проблема объекта только для FileStream чтения, предоставляя правильные аргументы конструктору FileStream.FileStream(String, FileMode, FileAccess) .

  • Состояние объекта заранее не известно, и объект не поддерживает определенную операцию. В большинстве случаев объект должен включать свойство или метод, указывающий, поддерживает ли он определенный набор операций. Исключение можно исключить, проверка значение объекта и вызов элемента только в случае необходимости.

    В следующем примере определяется DetectEncoding метод, который создает NotSupportedException исключение при попытке считывания с начала потока, который не поддерживает доступ на чтение.

    using System;
    using System.IO;
    using System.Threading.Tasks;
    
    public class TestPropEx1
    {
        public static async Task Main()
        {
            String name = @".\TestFile.dat";
            var fs = new FileStream(name,
                                    FileMode.Create,
                                    FileAccess.Write);
            Console.WriteLine("Filename: {0}, Encoding: {1}",
                              name, await FileUtilities1.GetEncodingType(fs));
        }
    }
    
    public class FileUtilities1
    {
        public enum EncodingType
        { None = 0, Unknown = -1, Utf8 = 1, Utf16 = 2, Utf32 = 3 }
    
        public async static Task<EncodingType> GetEncodingType(FileStream fs)
        {
            Byte[] bytes = new Byte[4];
            int bytesRead = await fs.ReadAsync(bytes, 0, 4);
            if (bytesRead < 2)
                return EncodingType.None;
    
            if (bytesRead >= 3 & (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF))
                return EncodingType.Utf8;
    
            if (bytesRead == 4)
            {
                var value = BitConverter.ToUInt32(bytes, 0);
                if (value == 0x0000FEFF | value == 0xFEFF0000)
                    return EncodingType.Utf32;
            }
    
            var value16 = BitConverter.ToUInt16(bytes, 0);
            if (value16 == (ushort)0xFEFF | value16 == (ushort)0xFFFE)
                return EncodingType.Utf16;
    
            return EncodingType.Unknown;
        }
    }
    // The example displays the following output:
    //    Unhandled Exception: System.NotSupportedException: Stream does not support reading.
    //       at System.IO.FileStream.BeginRead(Byte[] array, Int32 offset, Int32 numBytes, AsyncCallback callback, Object state)
    //       at System.IO.Stream.<>c.<BeginEndReadAsync>b__46_0(Stream stream, ReadWriteParameters args, AsyncCallback callback, Object state)
    //       at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance, TArgs](TInstance thisRef, TArgs args, Func`5 beginMethod, Func`3 endMethod)
    //       at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at System.IO.FileStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    //       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at FileUtilities.GetEncodingType(FileStream fs) in C:\Work\docs\program.cs:line 26
    //       at Example.Main() in C:\Work\docs\program.cs:line 13
    //       at Example.<Main>()
    
    open System
    open System.IO
    
    module FileUtilities =
        type EncodingType =
            | None = 0
            | Unknown = -1
            | Utf8 = 1
            | Utf16 = 2
            | Utf32 = 3
    
        let getEncodingType (fs: FileStream) = 
            task {
                let bytes = Array.zeroCreate<byte> 4
                let! bytesRead = fs.ReadAsync(bytes, 0, 4)
                if bytesRead < 2 then
                    return EncodingType.None
    
                elif bytesRead >= 3 && bytes[0] = 0xEFuy && bytes[1] = 0xBBuy && bytes[2] = 0xBFuy then
                    return EncodingType.Utf8
                else
                    let value = BitConverter.ToUInt32(bytes, 0)
                    if bytesRead = 4 && (value = 0x0000FEFFu || value = 0xFEFF0000u) then
                        return EncodingType.Utf32
                    else
                        let value16 = BitConverter.ToUInt16(bytes, 0)
                        if value16 = 0xFEFFus || value16 = 0xFFFEus then
                            return EncodingType.Utf16
                        else
                            return EncodingType.Unknown
            }
    
    let main _ = 
        task {
            let name = @".\TestFile.dat"
            let fs = new FileStream(name, FileMode.Create, FileAccess.Write)
            let! et = FileUtilities.getEncodingType fs
            printfn $"Filename: {name}, Encoding: {et}"
        }
    
    // The example displays the following output:
    //    Unhandled Exception: System.NotSupportedException: Stream does not support reading.
    //       at System.IO.FileStream.BeginRead(Byte[] array, Int32 offset, Int32 numBytes, AsyncCallback callback, Object state)
    //       at System.IO.Stream.<>c.<BeginEndReadAsync>b__46_0(Stream stream, ReadWriteParameters args, AsyncCallback callback, Object state)
    //       at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance, TArgs](TInstance thisRef, TArgs args, Func`5 beginMethod, Func`3 endMethod)
    //       at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at System.IO.FileStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    //       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
    //       at FileUtilities.GetEncodingType(FileStream fs)
    //       at Example.Main()
    //       at Example.<Main>()
    
    Imports System.IO
    Imports System.Threading.Tasks
    
    Module Example2
        Public Sub Main()
            Dim name As String = ".\TestFile.dat"
            Dim fs As New FileStream(name,
                                   FileMode.Create,
                                   FileAccess.Write)
            Console.WriteLine("Filename: {0}, Encoding: {1}",
                            name, FileUtilities2.GetEncodingType(fs))
        End Sub
    End Module
    
    Public Class FileUtilities2
        Public Enum EncodingType As Integer
            None = 0
            Unknown = -1
            Utf8 = 1
            Utf16 = 2
            Utf32 = 3
        End Enum
    
        Public Shared Function GetEncodingType(fs As FileStream) As EncodingType
            Dim bytes(3) As Byte
            Dim t As Task(Of Integer) = fs.ReadAsync(bytes, 0, 4)
            t.Wait()
            Dim bytesRead As Integer = t.Result
            If bytesRead < 2 Then Return EncodingType.None
    
            If bytesRead >= 3 And (bytes(0) = &HEF AndAlso bytes(1) = &HBB AndAlso bytes(2) = &HBF) Then
                Return EncodingType.Utf8
            End If
    
            If bytesRead = 4 Then
                Dim value As UInteger = BitConverter.ToUInt32(bytes, 0)
                If value = &HFEFF Or value = &HFEFF0000 Then
                    Return EncodingType.Utf32
                End If
            End If
    
            Dim value16 As UInt16 = BitConverter.ToUInt16(bytes, 0)
            If value16 = &HFEFF Or value16 = &HFFFE Then
                Return EncodingType.Utf16
            End If
    
            Return EncodingType.Unknown
        End Function
    End Class
    ' The example displays the following output:
    '    Unhandled Exception: System.NotSupportedException: Stream does not support reading.
    '       at System.IO.Stream.BeginReadInternal(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state,
    '     Boolean serializeAsynchronously)
    '       at System.IO.FileStream.BeginRead(Byte[] array, Int32 offset, Int32 numBytes, AsyncCallback userCallback, Object stat
    '    eObject)
    '       at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_0(Stream stream, ReadWriteParameters args, AsyncCallback callback, O
    '    bject state)
    '       at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func`5 beginMet
    '    hod, Func`3 endMethod)
    '       at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
    '       at System.IO.FileStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    '       at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count)
    '       at FileUtilities2.GetEncodingType(FileStream fs)
    '       at Example.Main()
    

    Исключение можно устранить, проверив значение FileStream.CanRead свойства и выход из метода, если поток доступен только для чтения.

        public static async Task<EncodingType> GetEncodingType(FileStream fs)
        {
            if (!fs.CanRead)
                return EncodingType.Unknown;
    
            Byte[] bytes = new Byte[4];
            int bytesRead = await fs.ReadAsync(bytes, 0, 4);
            if (bytesRead < 2)
                return EncodingType.None;
    
            if (bytesRead >= 3 & (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF))
                return EncodingType.Utf8;
    
            if (bytesRead == 4)
            {
                var value = BitConverter.ToUInt32(bytes, 0);
                if (value == 0x0000FEFF | value == 0xFEFF0000)
                    return EncodingType.Utf32;
            }
    
            var value16 = BitConverter.ToUInt16(bytes, 0);
            if (value16 == (ushort)0xFEFF | value16 == (ushort)0xFFFE)
                return EncodingType.Utf16;
    
            return EncodingType.Unknown;
        }
    }
    // The example displays the following output:
    //       Filename: .\TestFile.dat, Encoding: Unknown
    
    let getEncodingType (fs: FileStream) = 
        task {
            if not fs.CanRead then
                return EncodingType.Unknown
            else
                let bytes = Array.zeroCreate<byte> 4
                let! bytesRead = fs.ReadAsync(bytes, 0, 4)
                if bytesRead < 2 then
                    return EncodingType.None
    
                elif bytesRead >= 3 && bytes[0] = 0xEFuy && bytes[1] = 0xBBuy && bytes[2] = 0xBFuy then
                    return EncodingType.Utf8
                else
                    let value = BitConverter.ToUInt32(bytes, 0)
                    if bytesRead = 4 && (value = 0x0000FEFFu || value = 0xFEFF0000u) then
                        return EncodingType.Utf32
                    else
                        let value16 = BitConverter.ToUInt16(bytes, 0)
                        if value16 = 0xFEFFus || value16 = 0xFFFEus then
                            return EncodingType.Utf16
                        else
                            return EncodingType.Unknown
        }
    // The example displays the following output:
    //       Filename: .\TestFile.dat, Encoding: Unknown
    
    Public Class FileUtilities3
        Public Enum EncodingType As Integer
            None = 0
            Unknown = -1
            Utf8 = 1
            Utf16 = 2
            Utf32 = 3
        End Enum
    
        Public Shared Function GetEncodingType(fs As FileStream) As EncodingType
            If Not fs.CanRead Then
                Return EncodingType.Unknown
            End If
    
            Dim bytes(3) As Byte
            Dim t As Task(Of Integer) = fs.ReadAsync(bytes, 0, 4)
            t.Wait()
            Dim bytesRead As Integer = t.Result
            If bytesRead < 2 Then Return EncodingType.None
    
            If bytesRead >= 3 And (bytes(0) = &HEF AndAlso bytes(1) = &HBB AndAlso bytes(2) = &HBF) Then
                Return EncodingType.Utf8
            End If
    
            If bytesRead = 4 Then
                Dim value As UInteger = BitConverter.ToUInt32(bytes, 0)
                If value = &HFEFF Or value = &HFEFF0000 Then
                    Return EncodingType.Utf32
                End If
            End If
    
            Dim value16 As UInt16 = BitConverter.ToUInt16(bytes, 0)
            If value16 = &HFEFF Or value16 = &HFFFE Then
                Return EncodingType.Utf16
            End If
    
            Return EncodingType.Unknown
        End Function
    End Class
    ' The example displays the following output:
    '       Filename: .\TestFile.dat, Encoding: Unknown
    

Исключение NotSupportedException тесно связано с двумя другими типами исключений;

  • NotImplementedException

    Это исключение возникает, если метод может быть реализован, но не является, либо потому, что член будет реализован в более поздней версии, член недоступен на определенной платформе, либо член принадлежит абстрактному классу, а производный класс должен предоставить реализацию.

  • InvalidOperationException

    Это исключение возникает в сценариях, в которых, как правило, объект может выполнять запрошенную операцию, и состояние объекта определяет, может ли выполняться операция.

Заметки .NET Compact Framework

При работе с .NET Compact Framework и использованием P/Invoke в собственной функции это исключение может быть вызвано, если:

  • объявление в управляемом коде неправильно;
  • Платформа .NET Compact Framework не поддерживает то, что вы пытаетесь сделать.
  • имена библиотек DLL не подходят для экспорта.

NotSupportedException Если создается исключение, проверка:

  • Для любых нарушений ограничений .NET Compact Framework P/Invoke.
  • на наличие любых аргументов, требующих предварительного выделения памяти. Если они существуют, следует передавать ссылку на существующую переменную;
  • что имена экспортированных функций заданы верно. Это можно проверить с помощью DumpBin.exe.
  • что нет попыток передачи слишком большого числа аргументов.