我在作業中經常使用 C# 模式匹配,尤其是使用下面示例中所示的 switch/case。只要型別在 ViewModel 中傳遞,這些作業就很好,并且沒有問題,如下所示:
var fruit = new Apple();
MakePie(fruit);
.
private void MakePie(object fruit)
{
if (fruit != null)
{
Debug.WriteLine(fruit.GetType().Name);
switch (fruit)
{
case Apple _:
MakeApplePie();
break;
case Cherry _:
MakeCherryPie();
break;
}
}
}
但是,我發現如果我將型別作為 XAML 的CommandArgument傳遞,即使正確的型別作為引數傳遞,上述 switch/case 也會失敗——只是 switch/case 不再通過 C# 模式正確評估出于某種原因匹配。
<Button Content="Make Apple Pie" CommandParameter="{x:Type models:Apple}" Command="{Binding MakePie}"/>
<Button Content="Make Cherry Pie" CommandParameter="{x:Type models:Cherry}" Command="{Binding MakePie}"/>
所以只是為了執行一個簡單的確定,我使用了這個:
Debug.WriteLine(fruit.GetType().Name)
I was expecting to see either 'Apple' or 'Cherry', but instead, I got 'RuntimeType' as the name, even though I can clearly see from the fruit object that its type and type name match correctly to the 'Apple' or 'Cherry' classes from my models.
So can anyone explain or tell me if I am doing something wrong, or that I simply cannot pass the type from XAML to a switch/case pattern matching unless it is done from the ViewModel?
What would be the correct usage/implementation if you want to pass a type as a CommandArgument from XAML and also want the switch/case pattern matching to work?
To Amjad and dba:
Here, try the codes below on your end and let me know your results. Notice the private string TestSwitch(object t) function/method takes an object t as the argument. You will see that the switch pattern matching works just fine with t being an object. This is how I have implemented this pattern numerous times in other applications, but have always done it inside the ViewModel. First time trying to do it in XAML (no changes other than where the type is passed), and it doesn't work, and I can't seem to figure out the reason.
public partial class MainWindow : Window
{
public class TestClass1
{
public int MyProperty1 { get; set; }
}
public class TestClass2
{
public string MyProperty2 { get; set; }
}
public class TestClass3
{
public string MyProperty3 { get; set; }
}
public MainWindow()
{
InitializeComponent();
var t1 = new TestClass1();
Debug.WriteLine(TestSwitch(t1));
var t2 = new TestClass2();
Debug.WriteLine(TestSwitch(t2));
var t3 = new TestClass3();
Debug.WriteLine(TestSwitch(t3));
}
private string TestSwitch(object t)
{
switch (t)
{
case TestClass1 _:
return "TestClass1";
case TestClass2 _:
return "TestClass2";
case TestClass3 _:
return "TestClass3";
}
return "??????";
}
}
uj5u.com熱心網友回復:
我因長時間盯著代碼作業而大腦失靈,所以我找到了開關失敗的原因,并從那時起進行了重構,以使事情正常作業。
基本上,當您沒有可用的已切換型別的實際實體時,您不能使用基于 C# 型別的切換模式匹配功能,而是只有它的System.Type,這是我從 XAML 傳遞的內容。
因此,解決方案是將型別的實際實體作為物件型別傳遞,事情將按預期作業,或者使用類似以下的替代實作:
var type = parameter as Type; //where parameter is the passed argument of object type
switch (type)
{
case Type _ when type == typeof(Apple):
MakeApplePie();
break;
case Type _ when type == typeof(Cherry):
MakeCherryPie();
break;
}
uj5u.com熱心網友回復:
請嘗試我的方法:
xml:
<Button Text="Make Apple Pie" Command="{Binding TestComand}" CommandParameter="Apple" />
<Button Text="Make Cherry Pie" Command="{Binding TestComand}" CommandParameter="Cherry" />
視圖模型
public class fruitVM
{
public Command TestComand { get; set; }
public fruitVM()
{
TestComand = new Command<object>(func);
}
private void func(object obj)
{
string x = obj as string;
switch (x)
{
case "Cherry":
break;
case "Apple":
break;
}
}
}
uj5u.com熱心網友回復:
通過 XAML,您傳遞的是型別,而不是物件(型別的實體),因此 switch 陳述句找不到匹配項:
void Test ()
{
var res1 = ObjectVersusTypeCheck(new Apple()); //"It's an apple"
var res2 = ObjectVersusTypeCheck(typeof(Apple)); //"RuntimeType"
}
class Apple { }
private string ObjectVersusTypeCheck(object o)
{
switch (o)
{
case Apple _:
return "It`s an apple";
default:
return o.GetType().Name;
}
}
您可以執行以下操作:
void Test()
{
var res1 = ObjectVersusTypeCheck(new Apple()); //"apple"
var res2 = ObjectVersusTypeCheck(typeof(Apple)); //"apple"
var res3 = ObjectVersusTypeCheck(new Cherry()); //"cherry"
var res4 = ObjectVersusTypeCheck(typeof(Cherry));//"cherry"
}
private string ObjectVersusTypeCheck(object o)
{
Type type = null;
if (o is Type t)
{
type = t;
}
else
{
type = o.GetType();
}
if (type == typeof(Apple))
{
return "apple";
}
else if (type == typeof(Cherry))
{
return "cherry";
}
else
{
return "?";
}
}
class Apple { }
class Cherry { }
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/424240.html
