1 回答

TA貢獻(xiàn)1818條經(jīng)驗(yàn) 獲得超3個(gè)贊
dynamic
理論上,您可以使用或弱類型(如 )在 C# 中復(fù)制動(dòng)態(tài)類型系統(tǒng)object
。
但是,正如您在 Python 中所做的那樣,您將需要在運(yùn)行時(shí)不斷進(jìn)行類型一致性檢查
這是原始 Python 代碼的轉(zhuǎn)換dynamic
(不要這樣做)
public class Thing
{
? ? public Thing(int number) { Number = number; }
? ? public int Number { get; }
}
public class Thingy
{
? ? public Thingy(string text) { Text = text; }
? ? public string Text { get; }
}
public class ThisThing
{
? ? public ThisThing(dynamic chosenThing, string nameOfTheThing)
? ? {
? ? ? ? ChosenThing = chosenThing;
? ? ? ? NameOfTheThing = nameOfTheThing;
? ? }
? ? // Cache the accepted types
? ? private static readonly ICollection<Type> AcceptedTypes = new HashSet<Type> { typeof(Thing), typeof(Thingy) };
? ? private dynamic _chosenThing;
? ? public dynamic ChosenThing
? ? {
? ? ? ? get => _chosenThing;
? ? ? ? private set
? ? ? ? {
? ? ? ? ? ? if (!AcceptedTypes.Contains(value.GetType()))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? throw new ArgumentException($"ChosenThing must be {string.Join(" or ", AcceptedTypes.Select(t => t.Name))}");
? ? ? ? ? ? }
? ? ? ? ? ? _chosenThing = value;
? ? ? ? }
? ? }
? ? public string NameOfTheThing { get; }
}
根據(jù)您的測(cè)試用例,可以執(zhí)行以下操作:
var someThing = new Thing(10);
var anotherThing = new Thingy("10");
var newThing = new ThisThing(someThing, "Some Thing");
var anotherNewThing = new ThisThing(anotherThing, "Some Thing");
Console.WriteLine(newThing.ChosenThing.Number);
Console.WriteLine(anotherNewThing.ChosenThing.Text);
弱類型的問(wèn)題是錯(cuò)誤只能在運(yùn)行時(shí)被檢測(cè)到。下面的代碼都會(huì)通過(guò)編譯器(因?yàn)镃hosenThing是dynamic),但會(huì)在運(yùn)行時(shí)崩潰。
var invalidThing = new ThisThing("Invalid for string types", "Invalid");
// newThing has a Number, not a Text property
Console.WriteLine(newThing.ChosenThing.Text);
// Vice Versa
Console.WriteLine(anotherNewThing.ChosenThing.Number);
使用通用接口的更好方法
一種更容易接受的面向?qū)ο蠓椒ㄊ菫椤翱山邮艿摹鳖愋吞峁┮粋€(gè)公共基類或接口,然后使用它來(lái)代替。這樣您將獲得編譯時(shí)類型安全檢查。
// Common interface
public interface IThing { }
public class Thing : IThing
{
? ? public Thing(int number) { Number = number; }
? ? public int Number { get; }
}
public class Thingy : IThing
{
? ? public Thingy(string text) { Text = text; }
? ? public string Text { get; }
}
由于通用接口,IThing現(xiàn)在可以用于約束傳遞給的允許類型ThisThing(即必須符合約定IThing),并且這些類型約束在編譯時(shí)強(qiáng)制執(zhí)行:
public class ThisThing
{
? ? public ThisThing(IThing chosenThing, string nameOfTheThing)
? ? {
? ? ? ? ChosenThing = chosenThing;
? ? ? ? NameOfTheThing = nameOfTheThing;
? ? }
? ? public IThing ChosenThing { get; }
? ? public string NameOfTheThing { get; }
}
Thing您現(xiàn)在可以公開(kāi)合約之間以及Thingy通過(guò)合約的任何常見(jiàn)功能IThing。
就目前而言,該接口沒(méi)有通用性,因此您需要將 向下轉(zhuǎn)換IThing為子類之一,這再次違反了SOLID Liskov Substitution Principle:
Console.WriteLine(((Thing)newThing.ChosenThing).Number);
Console.WriteLine(((Thingy)anotherNewThing.ChosenThing).Text);
所以你真正想要的是抽象共性,例如
public interface IThing?
{?
? ? ?int CalculateValue();
}
現(xiàn)在,兩者Thing都Thingy將被迫提供此抽象的實(shí)現(xiàn),然后接口的使用者現(xiàn)在可以安全地使用該接口,而無(wú)需對(duì)具體實(shí)例的實(shí)際類型進(jìn)行任何進(jìn)一步的假設(shè):
Console.WriteLine(anyIThing.CalculateValue());
- 1 回答
- 0 關(guān)注
- 144 瀏覽
添加回答
舉報(bào)