C# 使用扩展方法将协变接口解构为值元组时的奇怪行为
这是我的协变接口,其中有一个方法返回且可枚举,该方法也是协变的(一如既往)。简单 现在我得到一个编译器错误,指出C# 使用扩展方法将协变接口解构为值元组时的奇怪行为,c#,tuples,covariance,variance,valuetuple,C#,Tuples,Covariance,Variance,Valuetuple,这是我的协变接口,其中有一个方法返回且可枚举,该方法也是协变的(一如既往)。简单 现在我得到一个编译器错误,指出TData数据必须是不变有效的。我明白了,ValueTuple不是协变的 好的,那么我将滚动我自己的非常特殊的元组,因为我真的希望能够在以后的foreach中使用好的解构语法: public interface IDataSource<out TData> { IAsyncEnumerable<IDataTuple<TData>> Stre
TData数据
必须是不变有效的。我明白了,ValueTuple
不是协变的
好的,那么我将滚动我自己的非常特殊的元组,因为我真的希望能够在以后的
foreach
中使用好的解构语法:
public interface IDataSource<out TData> {
IAsyncEnumerable<IDataTuple<TData>> StreamData(CancellationToken cancellationToken);
}
public interface IDataTuple<out TData> {
void Deconstruct(out TData data, out DateTime timestamp);
}
这就像一个魔咒。但是为什么呢将解构
声明为扩展方法而不是接口方法有什么区别?协方差从哪里停止,不变性从哪里开始
而且,out参数不应该是协方差有效的吗?我的意思是,它实际上是同一个关键字。这对我来说是有意义的。@DavidG有趣的是,在纯C#
中,out
参数可以是协变的,但是CLR的内部结构以及与其他.Net语言的兼容性使得它不可能实现,而且它们也被禁止。这至少解决了out
参数的谜团。谢谢,先生。@BrunoZell有趣的是,在纯C中,out参数可以与引用的问题共变,这表明out
参数在纯C中也不能共变。
public interface IDataSource<out TData> {
IAsyncEnumerable<(TData data, DateTime timestamp)>> StreamData(CancellationToken cancellationToken);
}
public interface IDataSource<out TData> {
IAsyncEnumerable<IDataTuple<TData>> StreamData(CancellationToken cancellationToken);
}
public interface IDataTuple<out TData> {
void Deconstruct(out TData data, out DateTime timestamp);
}
public interface IDataSource<out TData> {
IAsyncEnumerable<IDataTuple<TData>> StreamData(CancellationToken cancellationToken = default);
}
public interface IDataTuple<out TData> {
TData Data { get; }
DateTime Timestamp { get; }
}
public static class DataTupleExtensions {
public static void Deconstruct<TData>(this IDataTuple<TData> tuple, out TData data, out DateTime timestamp) {
data = tuple.Data;
timestamp = tuple.Timestamp;
}
}
public async Task StreamData<TData>(IDataSource<TData> dataSource, CancellationToken cancellationToken = default) {
await foreach (var (data, timestamp) in dataSource.StreamData(cancellationToken)) {
// Do stuff
}
}