首页 文章

.NET 4.0 Generic Invariant,Covariant,Contravariant

提问于
浏览
1

这是我面临的情景:

public abstract class Record { } 

public abstract class TableRecord : Record { } 

public abstract class LookupTableRecord : TableRecord { } 

public sealed class UserRecord : LookupTableRecord { } 

public interface IDataAccessLayer<TRecord> 
    where TRecord : Record { } 

public interface ITableDataAccessLayer<TTableRecord> : IDataAccessLayer<TTableRecord> 
    where TTableRecord : TableRecord { } 

public interface ILookupTableDataAccessLayer<TLookupTableRecord> : ITableDataAccessLayer<TLookupTableRecord> 
    where TLookupTableRecord : LookupTableRecord { } 

public abstract class DataAccessLayer<TRecord> : IDataAccessLayer<TRecord> 
    where TRecord : Record, new() { } 

public abstract class TableDataAccessLayer<TTableRecord> : DataAccessLayer<TTableRecord>, ITableDataAccessLayer<TTableRecord> 
    where TTableRecord : TableRecord, new() { } 

public abstract class LookupTableDataAccessLayer<TLookupTableRecord> : TableDataAccessLayer<TLookupTableRecord>, ILookupTableDataAccessLayer<TLookupTableRecord> 
    where TLookupTableRecord : LookupTableRecord, new() { } 

public sealed class UserDataAccessLayer : LookupTableDataAccessLayer<UserRecord> { }

现在,当我尝试将UserDataAccessLayer转换为它的通用基类型 ITableDataAccessLayer<TableRecord> 时,编译器会抱怨它无法隐式转换类型 .

当我尝试在通用参数的接口声明中使用 inout 关键字时,编译器会抱怨 Invalid variance: The type parameter must be invariantly valid.

我有以下抽象类:

public abstract class FileProcessor : IDisposable
{
    protected abstract ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer();
}

以及具体实施示例如下:

public class UserFileProcessor : FileProcessor
{
            protected override ITableDataAccessLayer<TableRecord> CreateTableDataAccessLayer()
        {
            return new UserDataAccessLayer();
        }
}

return new UserDataAccessLayer(); is where the compiler is complaining.

2 回答

  • 0

    据我所知,如果要使用协方差,则需要为接口指定out关键字 .

    http://geekswithblogs.net/NewThingsILearned/archive/2009/09/30/covariance-in-.net-4.0.aspx

  • 0

    共同和反差的问题在于它对所涉及的类型施加了相当多的限制,因此它可能并不适用于所有情况 .

    我设法通过进行以下更改来编译代码:

    public interface IDataAccessLayer<out TRecord>
        where TRecord : Record { }
    
    public interface ITableDataAccessLayer<out TTableRecord> : IDataAccessLayer<TTableRecord>
        where TTableRecord : TableRecord { }
    

    注意:

    为IDataAccessLayer和ITableDataAccessLayer添加了

    • out

    但是,这意味着您不仅限于在这些类型的输出位置使用TTableRecord,这意味着:

    • 类型用于只读属性(不适用于可写属性)

    • 方法的返回类型

    • out方法的参数类型

    你不能用它来:

    • 可写属性

    • ref或非out / ref参数的方法

    很可能,没有办法让co-contra和contra-variance帮助你 .

相关问题