如何在OCL中对关联对象属性进行空值校验?
OCL筛选集合元素的正确写法问题
需求背景
需要从Thing对象集合中筛选出满足以下条件的元素:
- Thing的
Other属性已分配有效对象(即thing.Other != null) - 该
Other对象的Title属性值不为null
对应的C#实现代码:
myThingCollection.Where(thing => thing.Other?.Title != null) .Whatever(...);
问题描述
尝试了以下OCL代码,但意外筛选出了thing.Other == null的对象:
myThingCollection->select(not other.title.isNull) ->collect(...whatever...)
询问是否必须使用以下写法,或是有更正确的实现方式:
myThingCollection->select((not other.isNull) and (not other.title.isNull)) ->collect(...whatever...)
解答
为什么初始写法出错
C#的?.是空安全访问运算符:如果thing.Other为null,直接返回null,后续!= null判断结果为false,不会选中这类元素。但OCL的逻辑不同:当访问null对象的属性(比如other.title在other为null时),表达式结果是invalid而非null。多数OCL处理器对invalid的逻辑判断行为特殊,比如not invalid.isNull会被判定为true,导致错误包含other为null的元素。
正确实现方式
你给出的第二个写法是完全正确的,必须同时显式检查两个条件:
myThingCollection->select((not other.oclIsNull()) and (not other.title.oclIsNull())) ->collect(...whatever...)
也可以用更简洁的oclIsNotNull()语法:
myThingCollection->select(other.oclIsNotNull() and other.title.oclIsNotNull()) ->collect(...whatever...)
这和C#的?.逻辑完全对应:先确保other是有效对象,再检查其title不为null,避免invalid值引发的错误判断。
OCL不支持类似C#的空安全访问语法,因此必须显式写出两个检查条件,没有更简化的等价写法。
内容的提问来源于stack exchange,提问作者Kjell Rilbe
相关产品推荐
相关产品推荐

