Skip to main content

How to Resolve Error "CS0077: The as operator must be used with a reference type or nullable type" in C#

The Compiler Error CS0077 is a type safety error involving the as operator. The message reads: "The as operator must be used with a reference type or nullable type ('int' is a non-nullable value type)."

The as operator is known as the "safe cast" operator. It attempts to convert an object to a specific type, and if the conversion fails, it returns null.

This error occurs because you are trying to cast to a non-nullable value type (like int, bool, double, or a struct). These types technically cannot hold a null value. Since the as operator's fail-safe mechanism relies on returning null, it physically cannot work with types that don't accept null.

Understanding the 'as' Operator logic

The syntax x as T roughly translates to: "Check if x is compatible with type T. If yes, return it as T. If no, return null."

  • Reference Types (string, class): Can be null. The as operator works.
  • Nullable Value Types (int?, bool?): Can be null. The as operator works.
  • Value Types (int, bool): Cannot be null. The as operator fails with CS0077.

Scenario 1: Casting to Primitive Types

The most common mistake is trying to safely extract a number or boolean from an object using as.

Example of error:

public void ProcessData(object input)
{
// input might be an integer, or it might be a string, or null.

// ⛔️ Error CS0077: 'int' is a non-nullable value type.
// If 'input' is NOT an integer, 'as' wants to return null.
// But 'number' (int) cannot hold null.
int number = input as int;
}

Solution 1: Use Nullable Types (Preserve Safety)

If you want to keep the "safe cast" behavior (where invalid input results in null instead of a crash), you must cast to a Nullable value type (T?).

public void ProcessData(object input)
{
// ✅ Correct: Cast to 'int?' (Nullable int)
int? number = input as int?;

if (number != null) // or number.HasValue
{
System.Console.WriteLine($"Success: {number.Value}");
}
else
{
System.Console.WriteLine("Conversion failed (input was not an int).");
}
}
note

This is the closest equivalent to how as works with reference types.

Solution 2: Use Explicit Casting (Throw Exception)

If you are certain the object is an integer, or if you want the program to crash (throw an InvalidCastException) when the data is wrong, use the standard Explicit Cast.

public void ProcessData(object input)
{
try
{
// ✅ Correct syntax, but risky behavior
// This will throw an exception if 'input' is not an int.
int number = (int)input;
System.Console.WriteLine($"Number: {number}");
}
catch (InvalidCastException)
{
System.Console.WriteLine("Cast failed.");
}
catch (NullReferenceException)
{
System.Console.WriteLine("Input was null.");
}
}

Solution 3: Use Pattern Matching (Modern Approach)

In modern C# (versions 7.0+), the is operator with Pattern Matching is the preferred way to handle this. It combines the check, the cast, and the assignment into one safe, readable step.

public void ProcessData(object input)
{
// ✅ Recommended: 'is' checks the type and assigns variable 'i' if successful.
if (input is int i)
{
// 'i' is a standard 'int' here, not nullable.
System.Console.WriteLine($"Success: {i}");
}
else
{
System.Console.WriteLine("Input is not an integer.");
}
}
tip

Pattern matching works for both Value Types (int) and Reference Types, making it a consistent coding style.

Conclusion

CS0077 protects you from logic errors where a failed cast would have nowhere to store its "failure" result.

  1. Understand as: It returns null on failure.
  2. Target Nullable Types: If you use as with a number, struct, or boolean, you must target int?, struct?, or bool?.
  3. Use Pattern Matching: Prefer if (obj is int i) over as for cleaner, safer code in modern C#.