次の方法で共有


CA1062: パブリック メソッドの引数の検証

TypeName

ValidateArgumentsOfPublicMethods

CheckId

CA1062

[カテゴリ]

Microsoft.Design

互換性に影響する変更点

なし

原因

引数が null (Visual Basic では Nothing) であるかどうかを確認せずに、外部から参照可能なメソッドが参照引数の 1 つを逆参照しています。

規則の説明

外部から参照可能なメソッドに渡されるすべての参照引数について、null かどうかをチェックする必要があります。引数が null の場合、ArgumentNullException をスローします。

メソッドがパブリックまたはプロテクトとして宣言されているために、未知のアセンブリから呼び出すことができる場合は、そのメソッドのすべてのパラメーターを検証する必要があります。メソッドが既知のアセンブリからのみ呼び出すことができるよう設計されている場合は、そのメソッドを内部メソッドとして設定し、そのメソッドを含むアセンブリに InternalsVisibleToAttribute 属性を適用する必要があります。

違反の修正方法

この規則違反を修正するには、各参照引数が null かどうかを検証します。

警告を抑制する状況

逆参照されるパラメーターが、関数の別のメソッド呼び出しによって検証されていることが確実な場合は、この規則からの警告を表示しないようにすることができます。

使用例

この規則に違反しているメソッドと、規則に適合するメソッドを次の例に示します。

Imports System

Namespace DesignLibrary

    Public Class Test

        ' This method violates the rule.
        Sub DoNotValidate(ByVal input As String)

            If input.Length <> 0 Then
                Console.WriteLine(input)
            End If

        End Sub

        ' This method satisfies the rule.
        Sub Validate(ByVal input As String)

            If input Is Nothing Then
                Throw New ArgumentNullException("input")
            End If

            If input.Length <> 0 Then
                Console.WriteLine(input)
            End If

        End Sub

    End Class

End Namespace
public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // Copy constructor CA1062 fires because other is dereferenced
    // without being checked for null
    public Person(Person other)
        : this(other.Name, other.Age)
    {
    }
}

using System;

namespace DesignLibrary
{
    public class Test
    {
        // This method violates the rule.
        public void DoNotValidate(string input)
        {
            if (input.Length != 0)
            {
                Console.WriteLine(input);
            }
        }

        // This method satisfies the rule.
        public void Validate(string input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (input.Length != 0)
            {
                Console.WriteLine(input);
            }
        }
    }
}

Visual Studio 2005 では、検証を行う別のメソッドにパラメーターが渡されるかどうかを、この規則で検出できませんでした。

Public Function Method(ByVal value As String) As String
    EnsureNotNull(value)

    ' Fires incorrectly    
    Return value.ToString()
End Function

Private Sub EnsureNotNull(ByVal value As String)
    If value Is Nothing Then
        Throw (New ArgumentNullException("value"))
    End If
End Sub
public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // Copy constructor
    public Person(Person other)
        : this(PassThroughNonNull(other).Name,
          PassThroughNonNull(other).Age)
    {
    }

    // Null check method
    private static Person PassThroughNonNull(Person person)
    {
        if (person == null)
            throw new ArgumentNullException("person");
        return person;
    }
}

public string Method(string value)
{
    EnsureNotNull(value);

    // Fires incorrectly    
    return value.ToString();
}

private void EnsureNotNull(string value)
{
    if (value == null)
        throw new ArgumentNullException("value");
}

参照オブジェクトであるフィールドまたはプロパティを設定するコピー コンストラクターを実行すると、CA1064 規則に違反する可能性があります。この違反が発生するのは、コピー コンストラクターに渡されるコピーされたオブジェクトが null (Visual Basic では Nothing) である可能性があるためです。この違反を解決するには、静的 (Visual Basic では共有) メソッドを使用して、コピーされたオブジェクトが null でないことを確認します。

次の Person クラスの例では、Person コピー コンストラクターに渡される other オブジェクトが null である可能性があります。

public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // Copy constructor CA1062 fires because other is dereferenced
    // without being checked for null
    public Person(Person other)
        : this(other.Name, other.Age)
    {
    }
}

次の Person の修正例では、コピー コンストラクターに渡される other オブジェクトが null であるかどうかが、PassThroughNonNull メソッドによって最初に確認されます。

public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // Copy constructor
    public Person(Person other)
        : this(PassThroughNonNull(other).Name, 
          PassThroughNonNull(other).Age)
    { 
    }

    // Null check method
    private static Person PassThroughNonNull(Person person)
    {
        if (person == null)
            throw new ArgumentNullException("person");
        return person;
    }
}