“Type”无法满足参数“TParam”的“new()”约束,因为“Type”具有必需的成员

问题描述 投票:0回答:3

我有这个类结构(简化):

public class InducingMedium
{
   public required string File { get; set; }
}

public class InducingVideo : InducingMedium {}
public class InducingAudio : InducingMedium {}

现在,我想一般实例化特定类型的实例:

public abstract class BaseInducingTests<TMedium>
    where TMedium : InducingMedium, new()
{
   protected async Task<IEnumerable<TMedium>> CreateInducingMedia(IEnumerable<string> files)
   {
      return files.Select(file =>
      {
          // Do some processing...

          return new TMedium
          {
              File = file,
          };
      });
   }
}

public class InducingVideosTests : BaseInducingTests<InducingVideo>
{
}

但是在派生类中我收到错误:

'Namespace.InducingVideo' cannot satisfy the 'new()' constraint 
on parameter 'TMedium' in the generic class 'Namespace.Tests.BaseInducingTests<TMedium>' 
because 'Namespace.InducingVideo' has required members

有没有办法在不引入反射的情况下解决这个问题?
我对

required
成员感到非常兴奋,它可以很好地处理可空类型,但现在我发现它有自己的警告:(

c# generics .net-7.0
3个回答
5
投票

这在docs中明确提到:

当类型参数包含 new() 约束时,具有任何必需成员的类型不能用作类型参数。编译器无法强制在通用代码中初始化所有必需的成员。

删除

required
修饰符或更改通用处理。例如通过ctor提供工厂:

public abstract class BaseInducingTests<TMedium>
    where TMedium : InducingMedium
{
    private readonly Func<string, TMedium> _init;

    public BaseInducingTests(Func<string, TMedium> init)
    {
        _init = init;
    }
    protected async Task<IEnumerable<TMedium>> CreateInducingMedia(IEnumerable<string> files)
    {
        return files.Select(file => _init(file));
    }
}

public class InducingVideosTests : BaseInducingTests<InducingVideo>
{
    public InducingVideosTests() : base(s => new InducingVideo{File = s})
    {
    }
}

如果需要,您可以创建一个包装器来支持满足

new()
约束的类:

public abstract class BaseNewableInducingTests<TMedium> : BaseInducingTests<TMedium>
    where TMedium : InducingMedium, new()
{
    protected BaseNewableInducingTests() : base(s => new TMedium { File = s })
    {
    }
}

3
投票

我刚刚发现的另一个解决方法是

SetsRequiredMembers
属性:

public class InducingVideosTests : BaseInducingTests<TestInducingVideo>
{
}

public class TestInducingVideo : InducingVideo
{
    [SetsRequiredMembers]
    public TestInducingVideo()
    {
    }
}

这违背了

required
成员的目的,但反思也是如此,并且出于测试目的,这是一种更简单的方法。

来源:https://code-maze.com/csharp-required-members/


0
投票

我开始在 Visual Studio 版本 17.9.5 中收到此错误,因为 Visual Studio 在保存时自动添加了

required
。这是由于代码清理所致。

错误 CS9040“FilesResponse”无法满足“new()”约束 泛型类型或方法“MyCode”中的参数“T”,因为 “FilesResponse”需要成员。

在新实例没有每个变量的情况下,通过简单地将类设置为可为空来解决这个问题。在你的情况下,这将是:

public class InducingMedium
{
   public string? File { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.