Fix: C# Cannot implicitly convert type 'X' to 'Y'
Quick Answer
How to fix C# cannot implicitly convert type error caused by type mismatches, nullable types, async return values, LINQ result types, and generic constraints.
The Error
You compile C# code and get:
error CS0029: Cannot implicitly convert type 'string' to 'int'Or variations:
error CS0029: Cannot implicitly convert type 'int?' to 'int'error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<int>' to 'System.Collections.Generic.IEnumerable<string>'error CS0266: Cannot implicitly convert type 'double' to 'float'. An explicit conversion exists (are you missing a cast?)error CS0029: Cannot implicitly convert type 'Task<string>' to 'string'You assigned or returned a value of one type where a different type is expected. C# does not allow implicit conversions between incompatible types, or between types where the conversion could lose data.
Why This Happens
C# is a statically typed language. Every variable, parameter, and return value has a declared type. When you assign a value of one type to a variable of another type, the compiler checks if an implicit conversion exists.
Implicit conversions are allowed when no data loss is possible:
int x = 42;
long y = x; // OK — int fits in long
double z = x; // OK — int fits in doubleImplicit conversions are NOT allowed when data could be lost or types are incompatible:
double d = 3.14;
int i = d; // Error — would lose decimal part
string s = 42; // Error — int is not a string
int? n = 5;
int x = n; // Error — nullable might be nullCommon causes:
- Wrong variable type. Assigning a
stringto anint, or vice versa. - Nullable type mismatch. Assigning
int?tointwithout handling the null case. - Missing await. Using the result of an async method without
await, gettingTask<T>instead ofT. - LINQ type mismatch. A LINQ query returns a different type than expected.
- Narrowing numeric conversion. Assigning a
doubleto afloat, or alongto anint. - Generic type mismatch. Passing
List<Derived>whereList<Base>is expected.
Fix 1: Use Explicit Casting
When the compiler says an explicit conversion exists, add a cast:
double d = 3.14;
int i = (int)d; // Explicit cast — truncates to 3
long bigNumber = 100L;
int smallNumber = (int)bigNumber; // Explicit cast — OK if value fits
float f = (float)d; // double → float — may lose precisionBe careful with overflow:
long huge = long.MaxValue;
int overflow = (int)huge; // Silent overflow — result is -1!
// Safer — throws OverflowException if value doesn't fit:
int safe = checked((int)huge);Pro Tip: Use
checkedblocks when casting between numeric types if the value might not fit. Withoutchecked, C# silently overflows, which can cause hard-to-find bugs. In production code, enable project-wide overflow checking with<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>in your.csproj.
Fix 2: Use Conversion Methods for String ↔ Number
You cannot cast between strings and numbers. Use conversion methods:
String to number:
string input = "42";
// Parse — throws if invalid
int number = int.Parse(input);
double d = double.Parse(input);
// TryParse — returns false if invalid (preferred)
if (int.TryParse(input, out int result))
{
Console.WriteLine(result);
}
// Convert class
int n = Convert.ToInt32(input);Number to string:
int number = 42;
string s = number.ToString();
string formatted = number.ToString("N2"); // "42.00"
string interpolated = $"{number}"; // String interpolationCommon mistake — casting instead of converting:
string s = "42";
int n = (int)s; // Error! Cannot cast string to int
int n = int.Parse(s); // CorrectFix 3: Handle Nullable Types
Nullable value types (int?, bool?, DateTime?) cannot be implicitly assigned to their non-nullable counterparts:
Broken:
int? nullable = GetValueOrNull();
int value = nullable; // Error: Cannot convert int? to intFixed — null-coalescing operator:
int value = nullable ?? 0; // Use 0 if nullFixed — explicit check:
if (nullable.HasValue)
{
int value = nullable.Value;
}Fixed — .Value (throws if null):
int value = nullable.Value; // InvalidOperationException if nullWith nullable reference types (C# 8+):
string? name = GetName();
string nonNull = name; // Warning: possible null reference
// Fixed:
string nonNull = name ?? "default";
string nonNull = name!; // Null-forgiving operator (you assert it's not null)Common Mistake: Using the null-forgiving operator (
!) to silence warnings without actually checking for null. This just moves the crash from compile time to runtime. Prefer??or explicit null checks.
Fix 4: Fix Async/Await Return Types
Forgetting await gives you a Task<T> instead of T:
Broken:
async Task<string> GetDataAsync()
{
return await httpClient.GetStringAsync("https://api.example.com/data");
}
// Calling without await:
string data = GetDataAsync(); // Error: Cannot convert Task<string> to stringFixed — add await:
string data = await GetDataAsync();Fixed — make the calling method async:
// Before:
public void ProcessData()
{
string data = GetDataAsync(); // Error
}
// After:
public async Task ProcessData()
{
string data = await GetDataAsync(); // Works
}Common variations:
// Wrong return type:
async Task<int> Calculate()
{
return "42"; // Error: Cannot convert string to int
}
// Missing async keyword:
Task<string> GetName()
{
return "Alice"; // Error: Cannot convert string to Task<string>
}
// Fixed:
async Task<string> GetName()
{
return "Alice"; // async methods wrap the return value in Task automatically
}
// Or without async:
Task<string> GetName()
{
return Task.FromResult("Alice");
}Fix 5: Fix LINQ Return Types
LINQ methods return specific types that might not match your variable:
Broken:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Where returns IEnumerable<int>, not List<int>
List<int> evens = numbers.Where(n => n % 2 == 0); // Error!
// Select changes the element type
List<int> strings = numbers.Select(n => n.ToString()); // Error! IEnumerable<string>
// FirstOrDefault returns int?, not int (in .NET 6+)
int first = numbers.FirstOrDefault(); // May warn about nullableFixed — convert to the expected type:
List<int> evens = numbers.Where(n => n % 2 == 0).ToList();
List<string> strings = numbers.Select(n => n.ToString()).ToList();
int[] array = numbers.Where(n => n > 3).ToArray();Fixed — use the correct variable type:
IEnumerable<int> evens = numbers.Where(n => n % 2 == 0);Use var to let the compiler infer the type:
var evens = numbers.Where(n => n % 2 == 0); // IEnumerable<int>
var first = numbers.FirstOrDefault(); // intFix 6: Fix Generic Covariance Issues
Generic types are not automatically covariant in C#:
Broken:
class Animal { }
class Dog : Animal { }
List<Dog> dogs = new List<Dog>();
List<Animal> animals = dogs; // Error! List<Dog> is not List<Animal>Fixed — use interfaces with covariance:
List<Dog> dogs = new List<Dog>();
IEnumerable<Animal> animals = dogs; // Works! IEnumerable<T> is covariant
IReadOnlyList<Animal> readOnly = dogs; // Also worksFixed — create a new list:
List<Animal> animals = dogs.Cast<Animal>().ToList();
// or
List<Animal> animals = new List<Animal>(dogs);
// or with LINQ
List<Animal> animals = dogs.Select(d => (Animal)d).ToList();Why: List<T> is invariant because it has both Add (input) and indexer (output) operations. If List<Dog> could be assigned to List<Animal>, you could add a Cat to the list through the List<Animal> reference, corrupting the List<Dog>.
IEnumerable<T> is covariant (declared with out T) because it only produces values, never consumes them.
Fix 7: Fix Enum Conversions
Enums and integers require explicit conversion:
enum Color { Red = 0, Green = 1, Blue = 2 }
// Broken:
Color c = 1; // Error: Cannot convert int to Color
int n = Color.Red; // Error: Cannot convert Color to int
// Fixed:
Color c = (Color)1; // Explicit cast — Green
int n = (int)Color.Red; // Explicit cast — 0
// String to enum:
Color c = Enum.Parse<Color>("Green"); // Color.Green
if (Enum.TryParse<Color>("Green", out Color result))
{
Console.WriteLine(result);
}Enum to string:
string name = Color.Red.ToString(); // "Red"
string name = nameof(Color.Red); // "Red" (compile-time constant)Fix 8: Fix Boolean Expression Issues
Common boolean conversion errors:
// Cannot convert int to bool (unlike C/C++):
int flag = 1;
if (flag) { } // Error in C#!
// Fixed:
if (flag != 0) { }
if (flag == 1) { }
// Cannot convert string to bool:
string input = "true";
bool b = input; // Error!
// Fixed:
bool b = bool.Parse(input);
bool b = input.Equals("true", StringComparison.OrdinalIgnoreCase);Conditional expression type mismatch:
// Both branches must return the same type:
var result = condition ? "hello" : 42; // Error: string vs int
// Fixed — make types match:
var result = condition ? "hello" : "42";
// or
object result = condition ? (object)"hello" : 42;Still Not Working?
Check for user-defined implicit conversions. Custom types can define implicit conversion operators:
public class Celsius
{
public double Temperature { get; }
public static implicit operator Celsius(double temp) => new Celsius(temp);
public static explicit operator double(Celsius c) => c.Temperature;
}
Celsius c = 100.0; // Uses implicit operator
double d = (double)c; // Uses explicit operatorCheck for interface vs concrete type. You might need to cast to an interface:
IMyInterface obj = new MyClass(); // Works if MyClass implements IMyInterface
MyClass obj2 = obj; // Error! Need explicit cast
MyClass obj2 = (MyClass)obj; // Works (throws if wrong type)
MyClass obj2 = obj as MyClass; // Returns null if wrong typeCheck for dynamic type. If you need late-bound behavior:
dynamic value = GetUnknownType();
int n = value; // Runtime conversion — may throw at runtimeFor C# null reference exceptions, see Fix: C# System.NullReferenceException: Object reference not set. For general type conversion in .NET, check the System.Convert class documentation.
Check your project’s nullable context. If you enabled <Nullable>enable</Nullable>, the compiler is stricter about nullable reference type assignments. Address warnings with proper null handling rather than suppressing them.
For TypeScript type errors that are similar in concept, see Fix: TypeScript cannot find name.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: C# async deadlock — Task.Result and .Wait() hanging forever
How to fix the C# async/await deadlock caused by Task.Result and .Wait() blocking the synchronization context in ASP.NET, WPF, WinForms, and library code.
Fix: C# System.NullReferenceException: Object reference not set to an instance of an object
How to fix C# NullReferenceException caused by uninitialized objects, null returns, LINQ results, async/await, dependency injection, and Entity Framework navigation properties.
Fix: C# TaskCanceledException: A task was canceled
How to fix C# TaskCanceledException A task was canceled caused by HttpClient timeouts, CancellationToken, request cancellation, and Task.WhenAll failures.
Fix: Angular ExpressionChangedAfterItHasBeenCheckedError
How to fix ExpressionChangedAfterItHasBeenCheckedError in Angular caused by change detection timing issues, lifecycle hooks, async pipes, and parent-child data flow.