Компилятор C# выдает ошибку недопустимых аргументов.Почему?

StackOverflow https://stackoverflow.com/questions/270334

  •  06-07-2019
  •  | 
  •  

Вопрос

У меня есть класс, который содержит два таких метода:

public String getFoo(Int32 a)
{
  return getBar(a, "b", null);
}

public String getBar(Int32 a, String b, Int32 c)
{
  //do something
  return "";
}

Однако когда я компилирую свой класс, я получаю две ошибки:

  1. Лучшее совпадение перегруженного метода для getBar(int,string,int) имеет несколько недопустимых аргументов.
  2. Аргумент «3»:невозможно преобразовать из '<null>'к 'int'

Кажется, я понимаю, почему я получаю эту ошибку:Компилятор не знает во время компиляции, каков реальный тип объекта.Может ли кто-нибудь подтвердить, прав ли я относительно причины ошибки, или указать настоящую причину?

Что еще более важно, могу ли я спроектировать свой код таким образом?Если да, то что мне нужно сделать, чтобы исправить ошибки?Причина, по которой я разработал свой класс таким образом, заключается в том, что я не хочу дублировать код в getBar и в getFoo.Эти два метода делают по сути одно и то же, за исключением того, что один из них принимает третий параметр.

Спасибо.

Это было полезно?

Решение

В .NET существует четкое понятие между ссылочными типами и типами значений.

Ссылочный тип — это объект, который размещается в куче (это будет подкласс System.Object).Все, что находится в стеке, — это указатель на этот объект.По этой причине совершенно допустимо хранить нулевой указатель.

Тип значения — это объект, который выделяется в стеке и является подклассом System.ValueType.Поскольку тип значения находится в стеке, при передаче его значения функции вы передаете все содержимое объекта.

Типы значений не могут быть нулевыми.

Большинство примитивных типов C# являются типами значений.Строка — это особый тип примитива, который на самом деле является ссылочным типом.

В .NET 2.0 MS добавила возможность заключать универсальный тип внутри структуры, чтобы он мог имитировать тип, допускающий значение NULL.На самом деле происходит то, что логика внутри структуры Nullable<T> эмулирует для вас значение null.

Они выразили это, используя сокращение синтаксиса, добавив к типу вопросительный знак, например:

int? nullableInt = null;
float? nullableFloat = null;

и т. д...

Если вам не нравится int?синтаксис, вы всегда можете использовать Nullable<SomeType>

public String getBar(Int32 a, String b, Nullable<Int32> c)

В качестве примечания: я предпочитаю добавлять перегрузку при выполнении того, что делаете вы, просто чтобы сделать синтаксис лучше.

public String getBar(Int32 a, String b)
{
     this.getBar(a,b,null);
}

public String getBar(Int32 a, String b, Nullable<Int32> c)
{
}

Другие советы

Попробуйте привести третий аргумент к getBar nullable int.

Итак, подпись будет выглядеть так:

public String getBar(Int32 a, String b, Int32? c)

Вы можете узнать больше о типах, допускающих значение NULL, в .NET. здесь и здесь.

Int32 это тип значения, что означает null не является допустимым аргументом для параметров типа Int32.

Если вам действительно нужны нулевые целые числа, используйте int? тип.

Две ошибки, которые вы видите, на самом деле являются одной и той же ошибкой.

Санни права.
Int32 является типом значения и не может содержать значение null.Если вам нужно передать «null» в качестве значения параметра, используйте Nullable вместо Int32 в качестве типа аргумента.

Вы можете найти дополнительную информацию на Типы, допускающие значение NULL (Руководство по программированию на C#) на MSDN.

Int32 — это псевдоним для int, который является типом значения или не допускающим значения NULL.Для версии с нулевым значением используйте System.Nullable или просто «int?».

Также не забудьте преобразовать обратно в необнуляемый int:

int? nullable = ...;
int non_nullable = nullable??0; 

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

Int32 не может иметь значение null.Вместо этого сделайте его типом, допускающим значение NULL:

public String getBar(Int32 a, String b, Int32? c)
{
    if (c.HasValue)
    {
        ...do something with c.Value...
    }
    return "";
}

Итак пятьсемь человек предложили int? как решение.Я предлагаю два других решения, которые мощь быть более уместным в зависимости от ситуации;

  • Создать перегрузку метода, который имеет только два аргумента, и опустите null при звонке:

    public String getFoo(Int32 a)
    {
      return getBar(a, "b", null);
    }
    
    public String getBar(Int32 a, String b)
    {
      //do something else, without the int
    }
    

    Хотя вы, вероятно, не захотите этого делать, поскольку заявили, что хотите избежать дублирования кода.

  • Использовать default вместо null:

    return getBar(a, "b", default(int));
    

    Кстати, это то же самое, что передать значение 0.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top