![](/img/trans.png)
[英]How to write Assert test with different cases on one method and all of them pass when comparing with different response cases?
[英]Unexpected need to assert Collection?.Method(...) in some but not all cases of parameters
注意。 問題不在於 null 參考保護器運算符 (X?.Y) 的含義。 我知道標題有點神秘,但我還沒有找到更好的方法來表述它。 對不起。
我正在使用FindOneAndReplaceAsync(...) ,根據它,選項的默認值為null
。
await Things.FindOneAndReplaceAsync(
x => x.Id == target.Id, replacement, null, token);
傳遞一個明確的null
就像預期的那樣工作。 但是,當我創建FindOneAndReplaceOptions的實例時,編譯器突然擔心 object 我正在執行未定義的搜索。
FindOneAndReplaceOptions<Thing> options = new FindOneAndReplaceOptions<Thing>();
await Things.FindOneAndReplaceAsync(
x => x.Id == target.Id, replacement, options, token);
為了編譯,我必須斷言Things
為非空。
FindOneAndReplaceOptions<Thing> options = new FindOneAndReplaceOptions<Thing>();
await Things?.FindOneAndReplaceAsync(
x => x.Id == target.Id, replacement, options, token);
雖然我理解這個建議,但我無法理解為什么只有在通過選項 object 的實例時才會出現投訴。 我檢查了我沒有因超載而絆倒。 即使沒有通過實際實例,也會出現同樣的現象,就像這樣。
FindOneAndReplaceOptions<Thing> options = null;
await Things?.FindOneAndReplaceAsync(
x => x.Id == target.Id, replacement, options, token);
這里發生了什么? 我感到很困惑...
這個很有趣。 如果你把它縮減到一個最小的復制器,你會得到這個:
#nullable enable
public class C
{
public void M(IMongoCollection<string>? collection)
{
// No warning
collection.FindOneAndReplaceAsync(null);
}
public void N(IMongoCollection<string>? collection)
{
// Warning
collection.FindOneAndReplaceAsync(new FindOneAndReplaceOptions<string>());
}
}
#nullable disable
public interface IMongoCollection<TDocument>
{
Task FindOneAndReplaceAsync<TProjection>(FindOneAndReplaceOptions<TDocument, TProjection> options = null);
}
public static class MongoCollectionExtensions
{
public static Task FindOneAndReplaceAsync<TDocument>(
this IMongoCollection<TDocument> doc,
FindOneAndReplaceOptions<TDocument, TDocument> options = null) => Task.CompletedTask;
}
public class FindOneAndReplaceOptions<TDocument, TProjection>
{
}
public class FindOneAndReplaceOptions<TDocument> : FindOneAndReplaceOptions<TDocument, TDocument>
{
}
在SharpLab上查看。
這實際上歸結為三件事:
null
接收器上調用擴展方法,但不能調用實例方法。請注意, IMongoCollection<TDocument>.FindOneAndReplaceAsync<TProjection>(...)
的簽名(這是此 MongoDB 方法的簡化版本)具有TProjection
類型參數,該參數鏈接到FindOneAndReplaceOptions<TDocument, TProjection>
參數。
如果您傳入null
作為options
的值,編譯器無法推斷TProjection
類型參數是什么,因此重載解析失敗,它會轉移到擴展方法上。
該FindOneAndReplaceAsync
擴展方法(這是此 MongoDB 方法的簡化版本)沒有TProjection
類型參數,其options
參數的類型為FindOneAndReplaceOptions<TDocument, TDocument>
)。
這意味着編譯器具有推斷所有類型參數所需的所有信息,即使您將null
作為options
的值傳遞也是如此。
因此,當您調用collection.FindOneAndReplaceAsync(null)
時,編譯器無法綁定到實例方法(因為它無法推斷TProjection
),並且必須綁定到擴展方法。
由於 MongoDB 沒有可空性注釋,編譯器根本不知道doc
參數的null
值是否被允許,因此它假定它是允許的。 因此,沒有可空性警告。
但是,當您傳入FindOneAndReplaceOptions<TDocument>
的實例(從FindOneAndReplaceOptions<TDocument, TDocument>
繼承時,編譯器有足夠的信息來推斷TProjection
的類型:它與TDocument
相同,因此它現在可以綁定到實例方法,並在可能是null
的東西上調用實例方法值得警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.