How to Resolve Error "CS0729: Type 'type' is defined in this assembly, but a type forwarder is specified for it" in C#
The Compiler Error CS0729 is a logical contradiction error related to Type Forwarding. The message reads: "Type 'MyClass' is defined in this assembly, but a type forwarder is specified for it".
Type Forwarding is a feature used when refactoring assemblies (DLLs). It allows you to move a class from Assembly A to Assembly B without breaking applications that were compiled against Assembly A. Assembly A keeps a "signpost" (Attribute) saying: "I don't have this class anymore; look in Assembly B."
The error occurs when an assembly contains both the actual source code definition of the class and the signpost saying the class is elsewhere. A type cannot simultaneously exist inside the assembly and be forwarded outside of it.
Understanding Type Forwarding
The attribute [TypeForwardedTo] is found in the System.Runtime.CompilerServices namespace. It is applied at the assembly level (usually in AssemblyInfo.cs or at the top of a file).
- Correct Usage: You moved
MyClasstoNewLib.dll. InOldLib.dll, you delete the class code and add[assembly: TypeForwardedTo(typeof(MyClass))]. - Incorrect Usage: You add the attribute to
OldLib.dll, but you forget to delete the class code fromOldLib.dll.
Scenario: The Contradiction
This error usually happens during a refactoring process where a developer intends to move a type but hasn't finished the process, or accidentally copies an attribute from another project.
Example of error: in this example, the project defines Widget explicitly, but also tries to forward Widget to another assembly.
using System.Runtime.CompilerServices;
// The Attribute says: "Widget is NOT here. It is in another assembly referenced by this project."
[assembly: TypeForwardedTo(typeof(Widget))]
namespace MyApp
{
// The Code says: "Widget IS here."
// ⛔️ Error CS0729: Type 'Widget' is defined in this assembly,
// but a type forwarder is specified for it.
public class Widget
{
public int Id { get; set; }
}
}
Solution 1: Keep the Definition (Remove Forwarder)
If your intention is for the class to live in this assembly (the one you are currently compiling), then the Type Forwarder is wrong.
Solution: simply remove the [TypeForwardedTo] attribute.
using System.Runtime.CompilerServices;
// ✅ Correct: Attribute removed.
// [assembly: TypeForwardedTo(typeof(Widget))] <--- Deleted
namespace MyApp
{
// The class remains defined here.
public class Widget
{
public int Id { get; set; }
}
}
Solution 2: Move the Type (Remove Definition)
If your intention was to move Widget to a new library (e.g., NewLibrary.dll) while keeping the current library (OldLibrary.dll) compatible with older apps, you must delete the code from the current project.
Solution:
- Reference the New Library: Ensure your current project references the DLL containing the actual
Widget. - Delete the Code: Remove the class definition from the current project.
- Keep the Forwarder: The attribute remains to point to the reference.
using System.Runtime.CompilerServices;
// ✅ Correct: The attribute points to 'Widget'.
// The compiler resolves 'typeof(Widget)' by looking at the REFERENCED assembly (NewLibrary.dll),
// not the source code of this file.
[assembly: TypeForwardedTo(typeof(Widget))]
namespace MyApp
{
// ✅ Correct: Class definition removed.
// public class Widget { ... } <--- Deleted
}
For this to work, typeof(Widget) must resolve. This implies you have added a Project Reference or Assembly Reference to the destination library.
Conclusion
CS0729 is a conflict between your code and your metadata attributes.
- Decide Location: Where should
MyClasslive? - If Here: Delete the
[TypeForwardedTo]attribute. - If There: Delete the
class MyClass { ... }code block from the current project and ensure you reference the destination assembly.