2

I'm new to C#, and this doesn't make a whole lot of sense. I'm converting a very simple class called User into another fairly simple class called InputCapsule. The problem I'm getting is the when returning the input capsule, VS says the following.

A user defined conversion must convert to or from the enclosing type.

I am quite confused, as I am returning the correct type. My code for reference:

(The Name, Email, and Pass are properties if that changes things.)

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hello
{
    public class InputCapsule<T>
    {
        public static explicit operator InputCapsule<string>(User v)
        {
            InputCapsule<string> @out = new InputCapsule<string>();
            @out.inputs.Add(v.Name);
            @out.inputs.Add(v.Email);
            @out.inputs.Add(v.Pass);
            return @out;
        }
        public List<T> inputs;
    }
} 
Michealal
  • 33
  • 3

2 Answers2

0

Either the source type or the destination type of the conversion operator must be the same as the type of the enclosing class/struct. Here, the enclosing class is InputCapsule<T>. Note that this is an open type. The destination type is InputCapsule<string> - a closed type. C# treats these very differently and considers them to be different types, even though they both start with InputCapsule. See open and closed types.

Just to demonstrate that they are indeed different types, I can declare a conversion from InputCapsule<T> to InputCapsule<string>:

public static explicit operator InputCapsule<string>(InputCapsule<T> v)
{
    return null;
}

If they are the same type, this would not be permitted according to the rules.

If you can change User, you should declare the conversion in User instead.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

Here for the "cast in (current type)" (I don't if this expression exist), you can't use a closed constructed generic type as a generic type parameter for the "name" of the explicit operator because the method definition is for open types (sorry if I don't use the good words).

Here you are not using the generic "method", you're defining it, because it takes a parameter being of type another than an InputCapsule<> (see @Sweeper answer about that I will call a "cast out (of current type)").

Thus here this generic type parameter T must be the same as the class itself as in InputCapsule<T>.

Therefore you can next check if T is string in the method body to allow or disallow (throw exception) the cast, or do anything else relevant.

You can for example write:

public class InputCapsule<T>
{
  public static explicit operator InputCapsule<T>(User v)
  {
    if ( typeof(T) == typeof(string) )
    {
      InputCapsule<string> instance = new InputCapsule<string>();
      instance.inputs.Add(v.Name);
      instance.inputs.Add(v.Email);
      instance.inputs.Add(v.Pass);
      return (InputCapsule<T>)(object)instance;
    }
    else
      throw new InvalidCastException();
  }
  public List<T> inputs = new List<T>();
}

public class User
{
  public string Name;
  public string Email;
  public string Pass;
}

To return the good type we use bosing and unboxing.

So you can implement any type conversion you need:

if ( typeof(T) == typeof(string) )
{
}
else
if ( typeof(T) == typeof(int) )
{
}
else
if ( typeof(T) == typeof(MyClass) )
{
}
else
  throw new InvalidCastException();

Also using the new switch pattern matching...

Test

  var user = new User { Name = "name", Email = "mail@mail.com", Pass = "pwd" };

  var inputcapsule = (InputCapsule<string>)user;

  Console.WriteLine(string.Join(Environment.NewLine, inputcapsule.inputs));

Output

name
mail@mail.com
pwd

User-defined conversion operators (C# reference)

What exactly is an "open generic type" in .NET?

Generics open and closed constructed types

Open and Closed Generic Types in C#