相关疑难解决方法(0)

为什么实现变体接口的类保持不变?

C#4.0进一步扩展了通用类型和接口的协方差和逆变.有些接口(比如IEnumerable<T>)是协变量,所以我可以这样做:

IEnumerable<object> ie = new List<string>();
Run Code Online (Sandbox Code Playgroud)

但是这条线怎么样?我遇到了编译时错误

List<Object> list = new List<String>();
//Cannot implicitly convert type List<string>' to List<object>'
Run Code Online (Sandbox Code Playgroud)

我的意思是,如果List<T>实现IEnumerable<T>为什么List<T>仍然是不变的?有没有一个很好的反例可以解释为什么在C#中不允许这样做?

c# ienumerable covariance c#-4.0

12
推荐指数
1
解决办法
2869
查看次数

可以/应该将任务<TResult>包装在C#5.0中,等待TResult中的协变吗?

我真的很喜欢使用C#5.0异步编程.但是,有些地方更新旧代码以与TAP模型保持一致会给我带来问题.

这是其中之一 - 我不确定为什么Task<TResult>在TResult中没有协变,但是在尝试更新协变接口以从同步模式转换为异步模式时,它会给我带来问题:

旧代码:

public interface IInitializable<out T> // ** out generic modifier **
{
    /// <summary>
    /// Boolean to indicate if class is ready
    /// </summary>
    bool IsInitialized { get; }

    /// <summary>
    /// Calls for instance to be initialized using current parameters
    /// Driver initialization can be done in the default constructor if desired
    /// </summary>
    T Initialize();
}
Run Code Online (Sandbox Code Playgroud)

新代码(不会编译):

public interface IAsyncInitializable<out T> // ** out generic modifier...broken **
{
    /// <summary>
    /// Boolean …
Run Code Online (Sandbox Code Playgroud)

c# covariance task-parallel-library async-await c#-5.0

11
推荐指数
2
解决办法
1463
查看次数

在非泛型方法中使用反射等待Task <TDerived>的结果

考虑以下情况:

class A
{
    public int Id;
}

class B : A
{

}

class Main
{
    public async Task<int> Create(Type type)
    {
        MethodInfo method = this.GetType().GetMethod("Create", new Type[] { typeof(string) }).MakeGenericMethod(new Type[] { type });
        A a = await (Task<A>)method.Invoke(this, new object[] { "humpf" });
        return a.Id;
    }

    public async Task<T> Create<T>(string name) where T : A
    {
        T t = await Foo.Bar<T>(name);
        return t;
    }
}
Run Code Online (Sandbox Code Playgroud)

呼叫new Main().Create(typeof(B))将失败

无法将' System.Threading.Tasks.Task[B]'类型的对象强制转换为' System.Threading.Tasks.Task[A]'

我不太明白,因为在这种情况下,Generic Create<T>方法只返回始终从' …

c# generics reflection async-await

9
推荐指数
1
解决办法
2347
查看次数

任务的协方差和逆变

鉴于以下片段,我完全不明白为什么即将实现的目标是不可能的:

接口:

public interface IEntityRepository<out T> : IRepository<IEntity> {

    void RequeryDataBase();

    IEnumerable<T> Search(string pattern);

    Task<IEnumerable<T>> SearchAsync(string pattern);

    SearchContext Context { get; }

    string BaseTableName { get; }
  }
Run Code Online (Sandbox Code Playgroud)

In IRepository<IEntity>只是简单的通用CRUD定义.

我在这一行得到错误: Task<IEnumerable<T>> SearchAsync(string pattern);

错误:

方法返回类型必须输出安全.无效方差:类型参数T必须在Task上无效

请帮我明白了,为什么我不能使用<out T>Task<T>

c# task covariance contravariance async-await

9
推荐指数
2
解决办法
2045
查看次数

为什么C#Func <interface> lambda表达式需要强制转换为结果

我需要更深入地了解Func类型表达式.

public class TheResult : IResultEntry {
    ...
}
Run Code Online (Sandbox Code Playgroud)

上面的类,为什么下面的第二种方法需要演员

我当然可以阅读错误信息,但很难理解.

// Success
public Task<IResultEntry> ProcessAsync_1()
{
    return Task.Factory.StartNew(() => (IResultEntry) new TheResult());
}

// Fail: Compiler error. Cannot implicitly convert...
public Task<IResultEntry> ProcessAsync_2()
{
    return Task.Factory.StartNew(() => new TheResult());
}
Run Code Online (Sandbox Code Playgroud)

如果我们在ReSharper的帮助下将其更改为命名方法,我们可以不进行强制转换.

public Task<IResultEntry> ProcessAsync_2_Changed()
{
    return Task.Factory.StartNew(function);
}

private IResultEntry function()
{
    return new TheResult();
}
Run Code Online (Sandbox Code Playgroud)

c# lambda func task-parallel-library

8
推荐指数
0
解决办法
56
查看次数

为什么 Task.FromResult 需要显式转换?

我有以下程序:

async Task Main()
{
    IList<int> myList = await TestAsync();
}

public Task<IList<int>> TestAsync()
{
    return Task.FromResult(new List<int>());
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨它无法在方法中将Task<List>a转换为 a :Task<IList>TestAsync

CS0029 无法将类型隐式转换 System.Threading.Tasks.Task<System.Collections.Generic.List<int>>System.Threading.Tasks.Task<System.Collections.Generic.IList<int>>

为什么它不知道我的方法返回 IList 的任务?

c#

6
推荐指数
1
解决办法
1186
查看次数

如果我“async”/“await”,为什么编译器只允许通用返回任务?

我正在尝试从通用函数 ( ) 返回特定类型的值GenericGetter

当我尝试简单地返回Task来自 的键入结果时GenericGetter,编译器向我显示以下错误:

Cannot convert expression type 'System.Threading.Tasks.Task<Example.ChildClass>' 
    to return type 'System.Threading.Tasks.Task<Example.BaseClass>'
Run Code Online (Sandbox Code Playgroud)

GenericGetter但是,如果我创建包含call 的函数async,并且返回等待的值,则编译器不会介意。它可以编译,可以工作,但对我来说,添加的 async/await 似乎是多余的。

为什么GetChildClass不编译,而却GetChildClassAsync 编译

这是我的例子:

namespace Example
{
    public class BaseClass {}
    public class ChildClass : BaseClass {}

    public class MyExample
    {
        private async Task Main()
        {
            var foo = await GetChildClass().ConfigureAwait(false);
            var bar = await GetChildClassAsync().ConfigureAwait(false);
        }

        private Task<BaseClass> GetChildClass() =>
            GenericGetter<ChildClass>();

        private async Task<BaseClass> GetChildClassAsync() =>
            await GenericGetter<ChildClass>().ConfigureAwait(false); …
Run Code Online (Sandbox Code Playgroud)

c# generics asynchronous async-await

5
推荐指数
1
解决办法
210
查看次数

如何从等待非通用任务中获得任务结果

我有以下方法:

public async Task Execute()
{
    object previous = null;

    // _delegates is of type IReadOnlyCollection<Delegate>
    foreach (Delegate method in _delegates) 
    {
        Task executing = (Task) (previous != null
           ? method.DynamicInvoke(_repository, previous)
           : method.DynamicInvoke(_repository);

        await executing;

        // pseudo code here
        if (executing returns something)
           previous = executing.Result //<-- ?
        else
           previous = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我遍历按顺序执行的代表列表。每个委托都会接收一个存储库作为参数,以及前一个委托的返回值(如果有)。

有些代表返回a Task,有些代表返回a Task<TResult>。如果遇到后者,我想将TResult值存储在其中,previous以便将其作为参数传递给下一个委托。

有没有办法做到这一点?

.net c# delegates task

3
推荐指数
1
解决办法
483
查看次数

为什么不编译?

我有这个代码:

static List<string> lst = new List<string>();

public static Task<IEnumerable<String>> GetStrings() {
    IEnumerable<String> x = lst;
    
    // This line below compiles just fine.
    // return Task.Run(() => x);
    
    // This line gives a compiler error:
    // Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Collections.Generic.List<string>>' to
    // 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<string>>'
    return Task.Run(() => lst);
}    
Run Code Online (Sandbox Code Playgroud)

为什么这一行编译得很好:return Task.Run(() => x); 虽然return Task.Run(() => lst);给出了编译器错误:

无法将类型“System.Threading.Tasks.Task<System.Collections.Generic.List>”隐式转换为“System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable>”

我认为既然List<string>IEnumerable<string>,我不应该显式设置x. 我的意思是,编译器知道lst是一个IEnumerable<string>.

我想我一定在这里遗漏了一些基本的东西。

c#

1
推荐指数
1
解决办法
125
查看次数