2009-04-05 4 views
14

Есть ли способ создать тип с нулевым значением в C# (например, DateTime или TimeSpan).?Не допускается использовать типы NULL

также есть способ (атрибут может быть) для обеспечения, что не нулевые аргументы не будут переданы к методам и свойствам без добавления

if(arg1 == null) 
{ 
    throw new ArgumentNullException("this attribute is null") 
} 

ответ

16

DateTime и TimeSpan не являются нулевыми, так как они struct s, а не class es.

Что касается вашего второго вопроса, то нет стандартного способа сделать это на C#. Вы можете сделать это, используя PostSharp, который представляет собой структуру AOP, или с Spec#, который представляет собой совершенно новый язык (расширение C#), что позволяет добиться некоторого желаемого поведения.

+5

Если вы используете шаг после сборки, то это абсолютно стандартный способ: Code Contracts официально входит в состав .NET 4 (и доступен отдельно для .NET 3.5). –

6

Не-обнуляемым типа является ValueType, другими словами, структура. Структура не может быть пустым, поэтому пример будет:

public struct MyStruct {} 

Там нет встроенного способа обеспечения, что нуль не передается в качестве параметра метода (если тип параметра не является ValueType) , Я видел, как люди создают методы расширения для выполнения более простых (т. Е. Меньше кода) утверждений о том, является ли параметр нулевым, это может быть для вас вариантом. С другой стороны, проверка начинается с самого начала; и цель проверки очень ясна. Это может быть не так, если вы используете собственный метод проверки.

C# 4.0 добавит лучшие варианты для выполнения такого рода программирования по контракту, но пока недоступен. Как указано в другом ответе PostSharp, вы можете делать то, что хотите. PostSharp работает, добавляя шаг после компиляции, где добавляется дополнительный код.

Есть несколько вариантов статической проверки того, может ли быть передан null. Например, ReSharper позволяет вам украсить ваши собственные параметры метода с помощью атрибута [NotNull], а ReSharper будет выдавать предупреждения во время компиляции, если он может определить, что параметр может быть нулевым. Конечно, это только предупреждает вас (потенциально) о плохой практике кодирования, это не проверка времени выполнения и не должна использоваться как таковая.

1

Переменные Structs (value type) никогда не будут нулевыми - это объясняет ваш случай DateTime. Поэтому, если ваши параметры метода являются структурами C#, вы можете быть уверены, что они никогда не будут пустыми.
Однако, если ваши параметры метода являются ссылочными типами, они могут быть пустыми. Я не думаю, что вы можете покончить с нулевой проверкой, как вы показали выше в этом случае.

11

Нулевая проверка, на которую вы ссылаетесь, будет проще в .NET 4.0/C# 4.0 с помощью кодовых контрактов, которая в значительной степени делает то, что вы хотите.

Структуры уже не имеют значения NULL, но не создавайте свои собственные структуры как сумасшедшие - вам редко нужны они (классы far более распространены). Не существует реальной концепции «класса, не допускающего нулевых значений»; люди предложили синтаксические изменения, как:

void Foo(string! arg1) {...} 

, который будет иметь компилятор делать непустой проверку на arg1 - но на самом деле, код-контракты делает это и многое другое. Есть несколько вещей, которые вы можете сделать в PostSharp, но, вероятно, это не стоит того.

Еще одна мысль о классе, не допускающем нулевой размер (и одна из причин, по которым они не реализованы); что будет default(T) для класса с нулевым значением? ; -p Спецификация требует, что определено default(T) ...

+0

+1 для кодовых контрактов. Именно то, что я думал! – Pwninstein

+0

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

+0

Для тех, кто читает это сейчас, Code Contracts теперь реализует статическую проверку. –

4

Вы правы: это недостаток в C# по сравнению с C++. Это позор, потому что 95% всех параметров, которые я передаю в функции, являются ненулевыми указателями. В C++ вы можете добавить документацию с проверкой компилятора, указав, какие указатели обеспечены, чтобы указать на что-то.

+1

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

0

Конечно, вы можете написать свои собственные типы значений (enum и struct), который не может быть пустым (если не сделано обнуляемым).

Что касается второй части, вы можете иметь общий параметр и ограничение принимать только типы значений, что означает, что аргумент не может быть нулевым - не очень полезно, учитывая подавляющее большинство случаев, мы используем class.

public static void Do<T>(T arg1) where T : struct 
{ 
    //both struct and enum goes here. 
} 
Смежные вопросы