有没有办法创建一个可以返回不同类型的方法,Predicate<BsonDocument> 或 FilterDefinition<BsonDocument>?

问题描述

我有以下代码

     IMongoCollection<BsonDocument> collection = _database.GetWriteCollection(typeName);
     collection.DeleteMany(x => includedIdentifiers.Contains((string)x["_id"]));

     List<BsonDocument> allRecords = await collection.Find(x => true)
         .ToListAsync();
     allRecords.RemoveAll(x => includedIdentifiers.Contains((string)x["_id"]));

我想减少重复并使其更具表现力,例如:

     IMongoCollection<BsonDocument> collection = _database.GetWriteCollection(typeName);
     collection.DeleteMany(IsContained(includedIdentifiers));

     List<BsonDocument> allRecords = await collection.Find(x => true)
         .ToListAsync();
     allRecords.RemoveAll(IsContained(includedIdentifiers));

如果 IsContained 定义如下,这实际上不会编译:

        private Predicate<BsonDocument> IsContained(HashSet<string> includedIdentifiers)
        {
            return x => includedIdentifiers.Contains((string)x["_id"]);
        }

错误

严重性代码描述项目文件行抑制状态 错误 CS1503 参数 1:无法从“System.Predicate”转换为“MongoDB.Driver.FilterDeFinition” SalesforceCache C:\projects\Salesforce Cache and Sync\SalesforceCache\Salesforce\ SalesforcSyncWorker.cs 488 活动

有没有一种方法(也许添加一些类型参数)可以让一个函数满足两个需求?

解决方法

在 C# 中,有没有办法创建一个可以返回一个类或另一个类的方法?

对问题标题的简短回答不,但是...

一个方法不能返回唯一的类型,也不能返回另一种类型,它们没有共同点,完全不同。

我们只能返回一个整数值(如 int),或一个值类型实例(如结构体),或一个引用值(如类)、元组或接口。

Why methods return just one kind of parameter in normal conditions?

除非我们有这些类型通用的基类或接口。

例如,如果 Predicate<>FilterDefinition<> 实现了 IMyInterface,我们可以返回一个或另一个对象作为这个接口:

IMyInterface MyMethod()
{
  if ( ... )
    return (IMyInterface)new Predicate<BsonDocument>();
  else 
    return (IMyInterface)new FilterDefinition<BsonDocument>();
}

因此,如果 Predicate<>FilterDefinition<> 有一个非泛型祖先来向上转换要返回的对象,或者实现一个非泛型接口来返回它,它会起作用。

非泛型,因为我们还没有通过 C# 中可用的菱形运算符获得 true generic polumorphism

我只是看到这些泛型类型似乎来自 MongoDB,如果是这样,根据此 documentation,它们没有任何共同点。

这是一个快速的想法,一个黑客,也许不是很干净,或者不是:返回一个元组(或结构或类),其中第一个项目为 A 类型,第二个项目为 B 类型。

一个为空,另一个不为空。

因此调用者可以检查并使用所提供的内容。

例如:

(Predicate<BsonDocument> predicate,FilterDefinition<BsonDocument> filterdefinition) MyMethod()
{
  if ( ... )
    return (new Predicate<BsonDocument>(),null);
  else 
    return (null,FilterDefinition<BsonDocument>());
}

这样使用:

var result = MyMethod();

if ( result.predicate != null && result.filterdefinition != null )
  throw new SystemException("Two instances provided: only one is expected.");
else
if (result.predicate != null)
{
  ...
}
else
if (result.filterdefinition != null)
{
  ...
}
else
  throw new SystemException("No instance provided: one is expected.");

这里抛出异常只是非常谨慎,可以省略,也可以不...