亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

創建一個可以是多種類型的構造函數屬性?

創建一個可以是多種類型的構造函數屬性?

C#
一只萌萌小番薯 2023-07-22 17:03:51
您好,我很想知道如何在 C# 中創建可以是多種類型的構造函數屬性。我可以按照下面的方式在 python 中生成我想要的內容。IE 初始化“this_thing”類的對象,該對象可以采用“thing”或“thingy”類的對象。與我想做的事情等效的Python工作是:class thing:? ? def __init__(self, number):? ? ? ? self.number = number? ? @property? ? def number(self):? ? ? ? return self._number? ? @number.setter? ? def number(self, value):? ? ? ? if not isinstance(value, int):? ? ? ? ? ? raise TypeError('"number" must be an int')? ? ? ? self._number = valueclass thingy:? ? def __init__(self, text):? ? ? ? self.text= text? ? @property? ? def text(self):? ? ? ? return self._text? ? @text.setter? ? def text(self, value):? ? ? ? if not isinstance(value, str):? ? ? ? ? ? raise TypeError('"text" must be a str')? ? ? ? self._text = valueclass this_thing:? ? def __init__(self, chosen_thing, name_of_the_thing):? ? ? ? self.chosen_thing = chosen_thing? ? ? ? self.name_of_the_thing = name_of_the_thing?? ? @property? ? def chosen_thing(self):? ? ? ? return self._chosen_thing? ? @chosen_thing.setter? ? def chosen_thing(self, value):? ? ? ? if (not isinstance(value, (thing, thingy))):? ? ? ? ? ? raise TypeError('"chosen_thing" must be a thing or thingy')? ? ? ? self._chosen_thing = value? ? @property? ? def name_of_the_thing(self):? ? ? ? return self._name_of_the_thing? ? @name_of_the_thing.setter? ? def name_of_the_thing(self, value):? ? ? ? if not isinstance(value, str):? ? ? ? ? ? raise TypeError('"name_of_the_thing" must be a str')? ? ? ? self._name_of_the_thing = valuesome_thing = thing(10)another_thing = thingy("10")new_thing = this_thing(some_thing, "Some Thing")another_new_thing = this_thing(another_thing, "Another Thing")在 C# 中,我有獨立工作的“Thing”和“Thingy”類。但我想創建一個新類“ThisThing”,它可以采用“Thing”類或“Thingy”類的對象,但我不確定如何啟用此操作。在 C# 中嘗試之后,看起來最可行的解決方案是將“ThisThing”類分成兩個單獨的類??磥?C# 在操作類類型方面不如 Python 靈活。當然,如果您知道如何在 C# 中重現上述 python 代碼,請發表評論。知道的話會很方便。
查看完整描述

1 回答

?
泛舟湖上清波郎朗

TA貢獻1818條經驗 獲得超3個贊

dynamic理論上,您可以使用或弱類型(如 )在 C# 中復制動態類型系統object。

但是,正如您在 Python 中所做的那樣,您將需要在運行時不斷進行類型一致性檢查

這是原始 Python 代碼的轉換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; }

}

根據您的測試用例,可以執行以下操作:


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);

弱類型的問題是錯誤只能在運行時被檢測到。下面的代碼都會通過編譯器(因為ChosenThing是dynamic),但會在運行時崩潰。


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);

使用通用接口的更好方法


一種更容易接受的面向對象方法是為“可接受的”類型提供一個公共基類或接口,然后使用它來代替。這樣您將獲得編譯時類型安全檢查。


// 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現在可以用于約束傳遞給的允許類型ThisThing(即必須符合約定IThing),并且這些類型約束在編譯時強制執行:


public class ThisThing

{

? ? public ThisThing(IThing chosenThing, string nameOfTheThing)

? ? {

? ? ? ? ChosenThing = chosenThing;

? ? ? ? NameOfTheThing = nameOfTheThing;

? ? }


? ? public IThing ChosenThing { get; }


? ? public string NameOfTheThing { get; }

}

Thing您現在可以公開合約之間以及Thingy通過合約的任何常見功能IThing。


就目前而言,該接口沒有通用性,因此您需要將 向下轉換IThing為子類之一,這再次違反了SOLID Liskov Substitution Principle:


Console.WriteLine(((Thing)newThing.ChosenThing).Number);

Console.WriteLine(((Thingy)anotherNewThing.ChosenThing).Text);

所以你真正想要的是抽象共性,例如


public interface IThing?

{?

? ? ?int CalculateValue();

}

現在,兩者Thing都Thingy將被迫提供此抽象的實現,然后接口的使用者現在可以安全地使用該接口,而無需對具體實例的實際類型進行任何進一步的假設:


Console.WriteLine(anyIThing.CalculateValue());


查看完整回答
反對 回復 2023-07-22
  • 1 回答
  • 0 關注
  • 135 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號