C# 自动遍历#
我需要做以下几点:C# 自动遍历#,c#,C#,我需要做以下几点: 获取T类型的参数并将其设置为当前 检查(当前).Parent是否存在且类型为A,如果存在,请转到那里 检查(当前).Owner是否存在,是否为类型B,如果存在,请转到那里 检查是否存在(电流)。任何存在且属于C型的,如果存在,则前往那里 返回(当前) 这相当于 C c = ((param).Parent as A).Owner as B).Whatever as C; 使用一些安全性来检查是否有任何“步骤”为空 问题是,我想遍历完全不同的类型和完全不同的属性。我需要在我的结
C c = ((param).Parent as A).Owner as B).Whatever as C;
使用一些安全性来检查是否有任何“步骤”为空
问题是,我想遍历完全不同的类型和完全不同的属性。我需要在我的结构中的几个不同的地方这样做。这可以通过某种方式实现自动化吗?也许可以使用lambdas、dynamics或某种泛型类?我在想这样的事情:
C c = Util.Traverse<C>(someObj, new[]
{
new Step { Path = p => p.Parent, ExpectedType = typeof(A) },
new Step { Path = p => p.Owner, ExpectedType = typeof(B) },
new Step { Path = p => p.Whatever, ExpectedType = typeof(C) }
});
C=Util.Traverse(someObj,new[]
{
新步骤{Path=p=>p.Parent,ExpectedType=typeof(A)},
新步骤{Path=p=>p.Owner,ExpectedType=typeof(B)},
新步骤{Path=p=>p.Whatever,ExpectedType=typeof(C)}
});
空传播表达式(即,它的计算结果不是NRE,而是null
)是被非正式地踢了几次的东西,但它只是不是C#中目前存在的一个特性
没有一个好的方法来写这个。“丑陋的单一声明”的版本是:
A a;
B b;
C c;
// ...
return (a = param.Parent as A) == null ? null :
(b = a.Owner as B) == null ? null :
(c = b.Whatever as C) == null ? null :
// ...
c.FinalThing;
就我个人而言,我只是把它分成许多部分(可能是在助手方法中):
空传播表达式(即,它的计算结果不是NRE,而是
null
)是被非正式地踢了几次的东西,但它根本不是C#中目前存在的特性
没有一个好的方法来写这个。“丑陋的单一声明”的版本是:
A a;
B b;
C c;
// ...
return (a = param.Parent as A) == null ? null :
(b = a.Owner as B) == null ? null :
(c = b.Whatever as C) == null ? null :
// ...
c.FinalThing;
就我个人而言,我只是把它分成许多部分(可能是在助手方法中):
我想你可以用lambdas来做这个
Func<T, A> step1 = p => (p.Parent != null && p.Parent is A) ? p.Parent as A : null;
Func<A, B> step2 = p => (p.Owner != null && p.Owner is B) ? p.Owner as B : null;
Func<B, C> step3 = p => (p.Whatever != null && p.Whatever is C) ? p.Whatever as C : null;
...
A a = step1(someObj) != null;
B b;
C c;
if (a != null)
b = step2(a);
if (b != null)
c = step3(b);
return c;
Func step1=p=>(p.Parent!=null&&p.Parent是A)?p、 父级为:null;
Func step2=p=>(p.Owner!=null&&p.Owner是B)?p、 所有者为B:null;
Func step3=p=>(p.Whatever!=null&&p.Whatever是C)?p、 C:null;
...
A=步骤1(someObj)!=无效的
B B;
C C;
如果(a!=null)
b=步骤2(a);
如果(b!=null)
c=步骤3(b);
返回c;
我认为您可以使用lambdas来实现这一点
Func<T, A> step1 = p => (p.Parent != null && p.Parent is A) ? p.Parent as A : null;
Func<A, B> step2 = p => (p.Owner != null && p.Owner is B) ? p.Owner as B : null;
Func<B, C> step3 = p => (p.Whatever != null && p.Whatever is C) ? p.Whatever as C : null;
...
A a = step1(someObj) != null;
B b;
C c;
if (a != null)
b = step2(a);
if (b != null)
c = step3(b);
return c;
Func step1=p=>(p.Parent!=null&&p.Parent是A)?p、 父级为:null;
Func step2=p=>(p.Owner!=null&&p.Owner是B)?p、 所有者为B:null;
Func step3=p=>(p.Whatever!=null&&p.Whatever是C)?p、 C:null;
...
A=步骤1(someObj)!=无效的
B B;
C C;
如果(a!=null)
b=步骤2(a);
如果(b!=null)
c=步骤3(b);
返回c;
如果您经常使用此方法,有时不得不使用自定义值而不是null,则可以编写如下扩展方法:
public static class Helper
{
public static U SafeCast<T, U>(this T obj, Expression<Func<T, object>> memberExpression, U defaultValue)
where T : class
where U : class
{
if (obj == null)
{
return defaultValue;
}
var me = memberExpression.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("memberExpression must be MemberExpression");
}
// TODO : Check for fields, not only properties
var memberValue = obj.GetType().GetProperty(me.Member.Name).GetValue(obj) as U;
if (memberValue != null)
{
return memberValue;
}
return defaultValue;
}
}
如果您经常使用此方法,并且有时必须使用自定义值而不是null,则可以编写如下扩展方法:
public static class Helper
{
public static U SafeCast<T, U>(this T obj, Expression<Func<T, object>> memberExpression, U defaultValue)
where T : class
where U : class
{
if (obj == null)
{
return defaultValue;
}
var me = memberExpression.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("memberExpression must be MemberExpression");
}
// TODO : Check for fields, not only properties
var memberValue = obj.GetType().GetProperty(me.Member.Name).GetValue(obj) as U;
if (memberValue != null)
{
return memberValue;
}
return defaultValue;
}
}
这个怎么样
public static void CastAndContinue<T>(object toCast, Action<T> nextStep)
{
if (toCast is T)
nextStep((T)toCast);
}
publicstaticvoidcastandcontinue(objecttocast,actionnextstep)
{
if(toCast是T)
下一步((T)到cast);
}
援引为:
//(param).Parent as A).Owner as B).Whatever as C
finalThing localResult = null;
CastAndContinue<A>(param.Parent,
p => CastAndContinue<B>(p.Owner,
x => CastAndContinue<C>(x.Whatever, z=> finalThing = z)
//(param)。父对象为A。所有者为B)。任意值为C
finalThing localResult=null;
CastAndContinue(参数Parent,
p=>CastAndContinue(p.Owner,
x=>CastAndContinue(x.Whatever,z=>finalThing=z)
这个怎么样
public static void CastAndContinue<T>(object toCast, Action<T> nextStep)
{
if (toCast is T)
nextStep((T)toCast);
}
publicstaticvoidcastandcontinue(objecttocast,actionnextstep)
{
if(toCast是T)
下一步((T)到cast);
}
援引为:
//(param).Parent as A).Owner as B).Whatever as C
finalThing localResult = null;
CastAndContinue<A>(param.Parent,
p => CastAndContinue<B>(p.Owner,
x => CastAndContinue<C>(x.Whatever, z=> finalThing = z)
//(param)。父对象为A。所有者为B)。任意值为C
finalThing localResult=null;
CastAndContinue(参数Parent,
p=>CastAndContinue(p.Owner,
x=>CastAndContinue(x.Whatever,z=>finalThing=z)
在您的指导下,我编写了两种不同的解决方案:
使用动态和lambdas:
在您的指导下,我编写了两种不同的解决方案: 使用动态和lambdas:
请注意,我使用了你们所有的解决方案来构建我的解决方案,但我无法将所有解决方案标记为已回答。因此,我选择了一个目前得分最少的解决方案。谢谢大家!请注意,我使用了你们所有的解决方案来构建我的解决方案,但我无法将所有解决方案标记为已回答。因此,我选择了一个目前得分最少的解决方案。谢谢大家!另一个有趣的方法是“maybe monad”。参见另一个有趣的方法是“maybe monad”。参见
C c = obj.Traverse(p => p.Parent as A)
.Traverse(p => p.Owner as B)
.Traverse(p => p.Whatever as C);