How to Resolve Warning "CS0684: 'interface' marked with 'CoClassAttribute' not marked with 'ComImportAttribute'" in C#
The Compiler Warning CS0684 is a configuration warning related to COM Interoperability. The message reads: "Interface 'MyInterface' marked with 'CoClassAttribute' not marked with 'ComImportAttribute'".
The [CoClass] attribute is a specialized feature used to tell the compiler: "If someone tries to write new MyInterface(), actually create an instance of this specific class instead." This behavior is part of the COM (Component Object Model) support in .NET. The compiler expects that if you are using this COM-specific mapping feature (CoClass), the interface itself should be marked as a COM import (ComImport). Without it, the compiler assumes you might be misusing the attribute on a standard managed interface.
This guide explains how to fix your attributes depending on whether you are doing COM Interop or trying to simulate this behavior in standard C#.
Understanding CoClass and ComImport
[CoClass(typeof(MyClass))]: This attribute allows syntax likeIMyInterface obj = new IMyInterface();. The compiler translates this intoIMyInterface obj = new MyClass();. This is used extensively in Office Interop libraries (e.g.,new Application()).[ComImport]: This attribute tells the CLR that the interface definition comes from an external COM type library (tlb/dll) and activates specific marshalling rules.
The compiler warns you because using [CoClass] on a standard, non-COM interface is unexpected and creates an ambiguous definition.
Scenario 1: Defining a COM Interface (Missing Attribute)
This usually happens when you are manually defining a COM interface (P/Invoke) to avoid referencing a massive interop assembly, but you forgot the required attributes to make it a valid COM definition.
Example of warning
using System.Runtime.InteropServices;
// The concrete implementation (usually abstract/empty in interop)
public class MyImplementation { }
// ⛔️ Warning CS0684: Interface marked with 'CoClassAttribute'
// not marked with 'ComImportAttribute'.
[CoClass(typeof(MyImplementation))]
[Guid("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE")] // GUID present
public interface IMyComInterface
{
void DoWork();
}
Solution: Add [ComImport]
If this is indeed a COM interface, you simply need to add the missing attribute.
using System.Runtime.InteropServices;
public class MyImplementation { }
// ✅ Correct: Both attributes are present.
[ComImport]
[CoClass(typeof(MyImplementation))]
[Guid("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE")]
public interface IMyComInterface
{
void DoWork();
}
Remember that [ComImport] also strictly requires a [Guid("...")]. If you add ComImport but miss the GUID, you will get Error CS0596.
Scenario 2: Trying to Use CoClass in Pure .NET
Sometimes developers discover [CoClass] and try to use it in standard C# code to enable "Default Interface Implementations" (allowing users to new an interface).
This is not what CoClass is for. In pure managed code, CoClass does not have the same effect as it does in COM, and relying on it is bad practice.
Example of warning
public class DefaultLogger : ILogger
{
public void Log() { }
}
// ⛔️ Warning CS0684
[CoClass(typeof(DefaultLogger))]
public interface ILogger
{
void Log();
}
public class Program
{
void Main()
{
// The developer wants this to work:
// ILogger log = new ILogger(); // Error: Cannot create instance of interface
}
}
Solution: Use Factory Pattern or DI
Do not use CoClass for pure .NET code. Instead, use a Factory pattern or Dependency Injection to supply the default implementation.
public interface ILogger
{
void Log();
}
public class DefaultLogger : ILogger
{
public void Log() { }
}
// ✅ Correct: Standard Factory Pattern
public static class LoggerFactory
{
public static ILogger Create()
{
return new DefaultLogger();
}
}
// Usage:
// var log = LoggerFactory.Create();
Conclusion
CS0684 is a configuration check for COM definitions.
- Is this COM Interop?
- Yes: You forgot
[ComImport]. Add it (and ensure you have a[Guid]). - No: You should not be using
[CoClass]. Remove the attribute and use a Factory pattern or Dependency Injection instead.
- Yes: You forgot