Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is "where T : class" not enforced in any way at compile time or run time?

In the following code, I pass a struct into a constructor that is expecting a class. Why does this compile and run without error (and produce the desired output)?

class Program
{
    static void Main()
    {
        var entity = new Foo { Id = 3 };
        var t = new Test<IEntity>(entity); // why doesn't this fail?
        Console.WriteLine(t.Entity.Id.ToString());
        Console.ReadKey();
    }
}

public class Test<TEntity> where TEntity : class
{
    public TEntity Entity { get; set; }

    public Test(TEntity entity)
    {
        Entity = entity;
    }

    public void ClearEntity()
    {
        Entity = null;
    }
}

public struct Foo : IEntity
{
    public int Id { get; set; }
}

public interface IEntity
{
    int Id { get; set; }
}

If I change my Main() method so that it includes a call to ClearEntity(), as shown below, it still generates no error. Why?

static void Main()
{
    var entity = new Foo { Id = 3 };
    var t = new Test<IEntity>(entity);
    Console.WriteLine(t.Entity.Id.ToString());
    t.ClearEntity(); // why doesn't this fail?
    Console.ReadKey();
}
like image 584
devuxer Avatar asked Sep 21 '12 19:09

devuxer


1 Answers

where TEntity : class forces TEntity to be a reference type, but an interface such as IEntity is a reference type.

See here: http://msdn.microsoft.com/en-us/library/d5x73970(v=vs.80).aspx

where T : class | The type argument must be a reference type, including any class, interface, delegate, or array type

Regarding your second question, you might think t.ClearEntity() would fail because it's assigning null to a variable whose type is a value type, but that's not the case. The compile-time type of Entity is the reference type IEntity, and the runtime type (after assignment) is the null type. So you never have a variable of type Foo but value null.

like image 75
Tim Goodman Avatar answered Nov 15 '22 00:11

Tim Goodman