Skip to main content

How to Resolve Error "CS0556: User-defined conversion must convert to or from the enclosing type" in C#

The Compiler Error CS0556 is a placement error regarding Operator Overloading. The message reads: "User-defined conversion must convert to or from the enclosing type".

In C#, user-defined conversion operators (marked with implicit or explicit) must logically belong to one of the types involved in the conversion. You cannot define a conversion between TypeA and TypeB inside a completely unrelated TypeC. At least one side of the conversion signature (the input parameter or the return type) must be the class or struct where the operator is defined.

This guide explains where to correctly place your conversion logic.

Understanding Operator Placement

When the compiler encounters a cast like (TypeB)myTypeA, it looks for a conversion operator definition inside:

  1. TypeA (The source type).
  2. TypeB (The destination type).

It does not search unrelated classes. Therefore, C# enforces that a conversion operator defined inside ClassX must either take ClassX as input or return ClassX as output.

  • Valid inside ClassX: operator ClassX(int i) (From int to X).
  • Valid inside ClassX: operator int(ClassX x) (From X to int).
  • Invalid inside ClassX: operator double(int i) (Converting int to double has nothing to do with X).

Scenario: Defining Conversion in a Third Party Class

This error often occurs when developers create a "Utility" or "Converter" class and try to define conversion operators between two other types there.

Example of error: attempting to define how Fahrenheit converts to Celsius inside a TemperatureConverter class.

public class Fahrenheit { public double Degrees; }
public class Celsius { public double Degrees; }

public class TemperatureConverter
{
// ⛔️ Error CS0556: User-defined conversion must convert to or from the enclosing type.
// The enclosing type is 'TemperatureConverter', but this method
// converts 'Fahrenheit' to 'Celsius'. Neither involves 'TemperatureConverter'.
public static implicit operator Celsius(Fahrenheit f)
{
return new Celsius { Degrees = (f.Degrees - 32) * 5 / 9 };
}
}

Solution: Move the Operator

You must move the operator definition inside either the Source class or the Destination class.

Option A: Define in Source Type

public class Fahrenheit 
{
public double Degrees;

// ✅ Correct: Defined inside Fahrenheit, taking Fahrenheit as input.
public static implicit operator Celsius(Fahrenheit f)
{
return new Celsius { Degrees = (f.Degrees - 32) * 5 / 9 };
}
}

Option B: Define in Destination Type

public class Celsius 
{
public double Degrees;

// ✅ Correct: Defined inside Celsius, returning Celsius.
public static implicit operator Celsius(Fahrenheit f)
{
return new Celsius { Degrees = (f.Degrees - 32) * 5 / 9 };
}
}

Option C: Use a Method (If you can't edit the types)

If Fahrenheit and Celsius come from third-party libraries (DLLs) and you cannot modify their code to add operators, you cannot create a user-defined conversion operator between them. You must use a standard static method instead.

public class TemperatureConverter
{
// ✅ Correct: Standard method, not an operator.
public static Celsius ToCelsius(Fahrenheit f)
{
return new Celsius { Degrees = (f.Degrees - 32) * 5 / 9 };
}
}

// Usage:
// var c = TemperatureConverter.ToCelsius(f);

Conclusion

CS0556 prevents "spooky action at a distance" where one class defines how two other classes behave.

  1. Check the Class: Look at the class containing the error.
  2. Check the Operator: Look at the signature operator Target(Source).
  3. Verify: Does Target or Source match the Class name?
    • Yes: The code is valid (check for other errors).
    • No: You must move the code to the Source or Target class, or change it to a normal method like Convert().