Open sandboxFocusImprove this doc

PS0087: Post.Cast Between Incompatible Types

Severity Error
Reported by PostSharp
Message Cannot perform a post-compilation static cast from type <SourceType> to type <TargetType>: cannot assign <SourceType> to <TargetType>.

Cause

An interface that an aspect introduces into a class is not visible to the C# compiler, so the source code cannot convert an instance of the class to this interface with a normal cast. The Cast<TSource, TTarget>(TSource) method fills this gap: the C# compiler accepts any pair of reference types, and PostSharp checks the conversion at build time, after the aspects have been applied, and then removes the call.

PostSharp reports PS0087 when <SourceType>, the first type argument of the call, cannot be assigned to <TargetType>, the second type argument, in the woven assembly. The usual cause is that no aspect introduces <TargetType> into <SourceType>: the aspect is not applied to this class, or it introduces another interface. The message is reported on the line of the call.

In the following example, the [Describable] aspect introduces the IDescribable interface into Customer, but it is not applied to Supplier.

using System;
using PostSharp;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

namespace Errors.PS0087_Error;

public interface IDescribable
{
    string Describe();
}

[PSerializable]
[IntroduceInterface( typeof(IDescribable) )]
public class DescribableAttribute : InstanceLevelAspect, IDescribable
{
    public string Describe() => $"Instance of {this.Instance!.GetType().Name}";
}

[Describable]
public class Customer
{
}

public class Supplier
{
}

public static class Program
{
    public static void Main()
    {
        IDescribable customer = Post.Cast<Customer, IDescribable>( new Customer() );
        Console.WriteLine( customer.Describe() );

        // The aspect is not applied to Supplier, so Supplier does not implement IDescribable.
        IDescribable supplier = Post.Cast<Supplier, IDescribable>( new Supplier() );
        Console.WriteLine( supplier.Describe() );
    }
}
error PS0087: PS0087_Error.cs(38,9): Cannot perform a post-compilation static cast from type Errors.PS0087_Error.Supplier to type Errors.PS0087_Error.IDescribable: cannot assign Errors.PS0087_Error.Supplier to Errors.PS0087_Error.IDescribable.

Resolution

  • Apply the aspect that introduces <TargetType> to <SourceType>, directly or by multicasting.
  • When the aspect is applied, check that it introduces <TargetType> and not another interface, for example with IntroduceInterfaceAttribute.
  • When the conversion is not meant to depend on an aspect, use a normal cast instead of Cast<TSource, TTarget>(TSource).

In the following example, the aspect is also applied to Supplier.

using System;
using PostSharp;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

namespace Errors.PS0087_Fixed;

public interface IDescribable
{
    string Describe();
}

[PSerializable]
[IntroduceInterface( typeof(IDescribable) )]
public class DescribableAttribute : InstanceLevelAspect, IDescribable
{
    public string Describe() => $"Instance of {this.Instance!.GetType().Name}";
}

[Describable]
public class Customer
{
}

// The aspect introduces IDescribable into Supplier too.
[Describable]
public class Supplier
{
}

public static class Program
{
    public static void Main()
    {
        IDescribable customer = Post.Cast<Customer, IDescribable>( new Customer() );
        Console.WriteLine( customer.Describe() );

        IDescribable supplier = Post.Cast<Supplier, IDescribable>( new Supplier() );
        Console.WriteLine( supplier.Describe() );
    }
}
Instance of Customer
Instance of Supplier

See Also

Reference

Cast<TSource, TTarget>(TSource)
IntroduceInterfaceAttribute

Other Resources

interface-introduction